Date: Mon Mar 30 13:35:28 2020
Scientist: Ran Yin
Sequencing (Waksman): Dibyendu Kumar
Statistics: Davit Sargsyan
Principal Investigator: Ah-Ng Kong

# Taxonomic Ranks:
# **K**ing **P**hillip **C**an n**O**t **F**ind **G**reen **S**ocks
# * Kingdom                
# * Phylum                    
# * Class                   
# * Order                   
# * Family     
# * Genus     
# * Species  
options(stringsAsFactors = FALSE,
        scipen = 999)
# # Increase mmemory size to 64 Gb----
# invisible(utils::memory.limit(65536))
# str(knitr::opts_chunk$get())
# # NOTE: the below does not work!
# knitr::opts_chunk$set(echo = FALSE, 
#                       message = FALSE,
#                       warning = FALSE,
#                       error = FALSE)
# require(knitr)
# require(kableExtra)
# require(shiny)
require(phyloseq)
require(data.table)
require(ggplot2)
require(plotly)
require(DT)
source("source/functions_may2019.R")
# On Windows set multithread=FALSE----
mt <- TRUE

1 Introduction

November 2018 Batch: Nrf2 KO (-/-) Mice
May 2019 Batch: Wild Type Mice

2 Data preprocessing

2.1 Raw Data

FastQ files were downloaded from Dr. Kumar’s DropBox. A total of 60 files (2 per sample, pair-ended) and 2 metadata files were downloaded.

2.2 Script

Data processing scripts (nrf2ubiome_dada2_nov2018_v1.Rmd and nrf2ubiome_dada2_may2019_v1.Rmd) were developed using DADA2 Pipeline Tutorial (1.12) with tips and tricks from the University of Maryland Shool of Medicine Institute for Genome Sciences (IGS) Microbiome Analysis Workshop (April 8-11, 2019). The oresults of the DADA2 scripts (data_nov2018/ps_nov2018.RData and data_may2019/ps_may2019.RData) are explored in this document.

3 Meta data: sample description

# Load data----
# Counts
load("data_nov2018/ps_nov2018.RData")
ps_nov2018 <- copy(ps)
rm(ps)
# Remove "Undetermined" sample
ps_nov2018 <- subset_samples(ps_nov2018, 
                             Name != "Undetermined_S0")
load("data_may2019/ps_may2019.RData")
gc(verbose = FALSE)
          used  (Mb) gc trigger  (Mb) max used  (Mb)
Ncells 4019072 214.7    7165308 382.7  6470341 345.6
Vcells 7844836  59.9   14786712 112.9 12249660  93.5
# Taxonomy (use the same one for both batches!)
load("data_may2019/taxa.RData")
taxa <- data.table(seq16s = rownames(taxa),
                   taxa)
# Samples
meta18 <- ps_nov2018@sam_data
datatable(meta18,
          options = list(pageLength = nrow(meta18)),
          caption = "Nrf2 KO (Nov 18) Meta Data")

meta19 <- ps_may2019@sam_data
datatable(meta19,
          options = list(pageLength = nrow(meta19)),
          caption = "WT (May 19) Meta Data")

4 OTUs mapped to Kingdoms, each batch separate

5 Merge the 2 data sets

pss <- merge_phyloseq(ps_nov2018,
                      ps_may2019)
tmp <- pss@sam_data
# Diet
meta <- data.table(Sample = rownames(pss@sam_data),
                   Diet = tmp$Diet)
meta$Diet <- gsub(x = meta$Diet, 
                  pattern = " Control",
                  replacement = "")
meta$Diet[!is.na(tmp$TREATMENT)] <- tmp$TREATMENT[!is.na(tmp$TREATMENT)]
meta$Diet <- gsub(x = meta$Diet,
                  pattern = "Control",
                  replacement = "AIN93M")
meta$Diet[is.na(meta$Diet)] <- "Pooled"
meta$Diet <- factor(meta$Diet,
                    levels = c("AIN93M",
                               "PEITC",
                               "Pooled"))
# Gemotype
meta$Genotype <- "Nrf2 KO"
meta$Genotype[is.na(tmp$Sex)] <- "Wild Type"
meta$Genotype <- factor(meta$Genotype,
                        levels = c("Wild Type",
                                   "Nrf2 KO"))
# Time
meta$Week <- as.numeric(as.character(tmp$Week)) - 4
meta$Week[meta$Genotype == "Wild Type"] <- as.numeric(gsub(x = tmp$WEEK[meta$Genotype == "Wild Type"],
                                                           pattern = "week ",
                                                           replacement = ""))
meta$Week <- paste("Week",
                   meta$Week)
meta$Week <- factor(meta$Week,
                    levels = c("Week 0",
                               "Week 1",
                               "Week 4",
                               "Week 5"))
# Mouse ID
meta$Mouse_Num <- as.numeric(as.character(tmp$MouseNum))
meta$Mouse_Num[meta$Genotype == "Wild Type"] <- as.numeric(substr(x = tmp$SAMPLE_NAME[meta$Genotype == "Wild Type"],
                                                                  start = 3, 
                                                                  stop = 3))
# Cage number
meta$Cage <- as.character(tmp$Cage)
meta$Cage[meta$Genotype == "Wild Type"] <- substr(x = tmp$SAMPLE_NAME[meta$Genotype == "Wild Type"],
                                                  start = 2, 
                                                  stop = 2)
meta$Cage <- factor(meta$Cage)
meta <- data.frame(meta)
rownames(meta) <- meta$Sample
meta
# Edit meta data
sample_data(pss) <- meta
pss@sam_data
Sample Data:        [69 samples by 6 sample variables]:
dim(pss@otu_table@.Data)
[1]    69 17046
# Remove OTU unmapped to Bacteria
ps0 <- subset_taxa(pss, 
                   Kingdom == "Bacteria")
dim(ps0@otu_table@.Data)
[1]    69 16351

6 OTU table (first 10 rows)

7 Total counts per sample (i.e. sequencing depth)

p1 <- ggplot(smpl,
             aes(x = Sample,
                 y = Total,
                 group =Diet,
                 fill = Diet)) +
  facet_wrap(~ Genotype + Week,
             scale = "free") +
  geom_bar(stat = "identity",
           color = "black") +
  scale_x_discrete("") +
  scale_y_continuous("Number of Reads") +
  scale_fill_grey("Treatment", 
                  start = 0.1, 
                  end = 1,
                  na.value = "red",
                  aesthetics = "fill") +
  theme_bw() + 
  theme(panel.border = element_blank(), 
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(), 
        axis.title.x = element_blank(),
        # axis.text.x = element_blank(),
        axis.text.x = element_text(angle = 45,
                                   hjust = 1),
        # axis.ticks.x=element_blank(),
        legend.position = "top")
tiff(filename = "tmp/seq_depth_nov2018_may2019.tiff",
     height =6,
     width = 8,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p1)
graphics.off()
print(p1)

t2 <- data.table(table(tax_table(ps0)[, "Phylum"],
                                  exclude = NULL))
t2$V1[is.na(t2$V1)] <- "Unknown"
setorder(t2, -N)
t2[, pct := N/sum(N)]
setorder(t2, -N)
colnames(t2) <- c("Phylum",
                  "Number of OTUs",
                  "Percent of OTUs")
datatable(t2,
          rownames = FALSE,
          caption = "Number of Bacterial OTUs by Phylum",
          class = "cell-border stripe",
          options = list(search = FALSE,
                         pageLength = nrow(t2))) %>%
  formatCurrency(columns = 2,
                 currency = "",
                 mark = ",",
                 digits = 0) %>%
  formatPercentage(columns = 3,
                   digits = 2)

ps1 <- subset_taxa(ps0, 
                   !is.na(Phylum))
dim(ps1@otu_table@.Data)
[1]    69 15919

8 Remove Phylum

Remove:
1. Unmapped OTUs (“Unknown”).
2. Cyanobacteria: aerobic, photosynthesizing bacteria that probably got into the sample through food.
NOTE: Chloroflexi might be ok.

ps0 <- subset_taxa(ps0,
                   !(Phylum %in% c("Unknown",
                                   "Cyanobacteria")))

9 Richness (Alpha diversity)

Shannon index (aka Shannon enthrophy) is calculated as:
H’ = -sum(1 to R)p(i)ln(p(i)) When there is exactly 1 type of data (e.g. a single species in the sample), H’=0. The opposite scenario is when there are R>1 species present in the sample in the exact same amounts and H’=ln(R).

Shannon’s diversity index was calculated for each sample and ploted over time.

shannon.ndx <- estimate_richness(ps0,
                                 measures = "Shannon")
shannon.ndx <- data.table(Sample = rownames(shannon.ndx),
                          shannon.ndx)
smpl <- merge(smpl,
              shannon.ndx,
              by = "Sample")
p1 <- ggplot(smpl,
             aes(x = Total,
                 y = Shannon,
                 fill = Genotype,
                 shape = Week)) +
  geom_point(size = 2) +
  scale_shape_manual(breaks = unique(smpl$Week),
                     values = 21:24)
tiff(filename = "tmp/shannon_vs_depth_nov18_may19.tiff",
     height = 5,
     width = 6,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p1)
graphics.off()
ggplotly(p1)

Even though estimate_richness function does not adjust for the sequencing depth, there is no correlation between the index and the sample’s sequecing depth. Proceed with the comparison.

10 Shannon idex over time

p1 <- plot_richness(ps0,
                    x = "Week", 
                    measures = "Shannon") +
  facet_wrap(~ Genotype,
             scale = "free_x") +
  geom_line(aes(group = paste0(Diet,
                               Cage,
                               Mouse_Num)),
            color = "black") +
  geom_point(aes(fill = Diet),
             shape = 21,
             size = 3,
             color = "black") +
  scale_x_discrete("") +
  theme(axis.text.x = element_text(angle = 30,
                                   hjust = 1,
                                   vjust = 1))
ggplotly(p = p1,
         tooltip = c("Mouse_Num",
                     "value"))

p1 <- p1 + 
  scale_fill_discrete("") +
  theme(legend.position = "top")
tiff(filename = "tmp/shannon_nov18_may19.tiff",
     height = 5,
     width = 8,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p1)
graphics.off()

The plot above suggests that the largest differences in alpha diversity (as measured by Shannon’s index) are in genotype. THis was also confirmed in the 3rd study (September 2019 batch)

11 Average Shannon Index

# Average shannon index by treatment group
tmp <- data.table(copy(smpl))
tmp[, mu := mean(Shannon),
    by = list(Diet,
              Genotype,
              Week)]
tmp[, sem := sd(Shannon)/sqrt(.N),
    by = list(Diet,
              Genotype,
              Week)]
tmp <- unique(tmp[, c("Diet",
                      "Genotype",
                      "Week",
                      "mu",
                      "sem")])
p1 <- ggplot(tmp,
             aes(x = Week,
                 y = mu,
                 ymin = mu - sem,
                 ymax = mu + sem,
                 fill = Diet,
                 group = Diet)) +
  facet_wrap(~ Genotype,
             scale = "free_x") +
  geom_errorbar(position = position_dodge(0.3),
                width = 0.4) +
  geom_line(position = position_dodge(0.3)) +
  geom_point(size = 3,
             shape = 21,
             position = position_dodge(0.3)) +
  scale_x_discrete("") +
  scale_y_continuous("Shannon Index") +
  scale_fill_grey("Treatment", 
                  start = 0, 
                  end = 1,
                  na.value = "red",
                  aesthetics = "fill") +
  theme_bw() + 
  theme(panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(), 
        # panel.border = element_blank(), 
        axis.title.x = element_blank(),
        # axis.text.x = element_blank(),
        axis.text.x = element_text(angle = 45,
                                   hjust = 1),
        axis.ticks.x=element_blank(),
        legend.position = "top")
tiff(filename = "tmp/avg_shannon_nov18_may19.tiff",
     height = 4,
     width = 6,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p1)
graphics.off()
print(p1)

NOTE: cannot test diet effect because of unassigend pooled samples in the KO mice. For the same reason, cannot use mixed effects model on the whole data set. At best, testing genotype and time trend by assuming Week 4 in WT = Week 5 in KO.

smpl$Timepoint <- as.numeric(smpl$Week)
smpl$Timepoint[smpl$Timepoint == 4] <- 3
m1 <- lm(Shannon ~ Timepoint*Genotype,
         data = smpl)
summary(m1)

Call:
lm(formula = Shannon ~ Timepoint * Genotype, data = smpl)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.45931 -0.09344  0.02849  0.08560  0.34790 

Coefficients:
                          Estimate Std. Error t value            Pr(>|t|)    
(Intercept)                6.55295    0.08207  79.842 <0.0000000000000002 ***
Timepoint                  0.04053    0.03799   1.067              0.2900    
GenotypeNrf2 KO            0.35620    0.13511   2.636              0.0105 *  
Timepoint:GenotypeNrf2 KO  0.09221    0.05778   1.596              0.1154    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.1699 on 65 degrees of freedom
Multiple R-squared:  0.7687,    Adjusted R-squared:  0.7581 
F-statistic: 72.02 on 3 and 65 DF,  p-value: < 0.00000000000000022

No significant time trend; significantly higher alpha diversity in the Nrf2 KO mice. This is possibly a batch effect but we observed same trend in Study 3 (Crabbery and PEITC with both genotypes in the same study).

12 Bacteriotides vs. Firmicutes

counts_p <- counts_by_tax_rank(dt1 = otu,
                               aggr_by = "Phylum")
fb <- t(counts_p[Phylum %in% c("Bacteroidetes",
                               "Firmicutes"), -1])
fb <- data.table(Sample = rownames(fb),
                 Bacteroidetes = fb[, 1],
                 Firmicutes = fb[, 2])
fb <- data.table(merge(meta,
            fb,
            by = "Sample"))
p1 <- ggplot(fb,
             aes(x = log2(Bacteroidetes),
                 y = log2(Firmicutes),
                 fill = Genotype)) +
  geom_point(size = 2,
             color = "black",
             shape = 21)
p2 <- ggplot(fb,
             aes(x = log2(Bacteroidetes),
                 y = log2(Firmicutes),
                 fill = Week)) +
  geom_point(size = 2,
             color = "black",
             shape = 21)
p3 <- ggplot(fb,
             aes(x = log2(Bacteroidetes),
                 y = log2(Firmicutes),
                 fill = Diet)) +
  geom_point(size = 2,
             color = "black",
             shape = 21)
p4 <- ggplot(fb,
             aes(x = Week,
                 y = Bacteroidetes/Firmicutes,
                 fill = Diet,
                 group = paste0(Diet,
                               Cage,
                               Mouse_Num))) +
  facet_grid(~ Genotype,
             scale = "free_x") +
  geom_hline(yintercept = 1,
             linetype = "dashed") +
  geom_line(position = position_dodge(0.3)) +
  geom_point(size = 2,
             color = "black",
             shape = 21,
             position = position_dodge(0.3))  +
  theme_bw() + 
  theme(panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(), 
        # panel.border = element_blank(), 
        axis.title.x = element_blank(),
        # axis.text.x = element_blank(),
        axis.text.x = element_text(angle = 45,
                                   hjust = 1),
        axis.ticks.x=element_blank(),
        legend.position = "top")
tiff(filename = "tmp/bact_vs_firm_nov18_may19.tiff",
     height = 6,
     width =8,
     units = "in",
     res = 600,
     compression = "lzw+p")
gridExtra::grid.arrange(p1, p2, p3, p4)
graphics.off()
gridExtra::grid.arrange(p1, p2, p3, p4)

fb[, mu := mean(Bacteroidetes/Firmicutes),
   by = c("Diet",
          "Genotype",
          "Week")]
fb[, sem := sd(Bacteroidetes/Firmicutes)/sqrt(.N),
   by = c("Diet",
          "Genotype",
          "Week")]
mufb <- unique(fb[, c("Diet",
                      "Genotype",
                      "Week",
                      "mu",
                      "sem")])
p1 <- ggplot(mufb,
             aes(x = Week,
                 y = mu,
                 ymin = mu - sem,
                 ymax = mu + sem,
                 fill = Diet,
                 group = Diet)) +
  facet_wrap(~ Genotype,
             scale = "free_x") +
  geom_hline(yintercept = 1,
             linetype = "dashed") +
  geom_errorbar(position = position_dodge(0.3),
                width = 0.4) +
  geom_line(position = position_dodge(0.3)) +
  geom_point(size = 3,
             shape = 21,
             position = position_dodge(0.3)) +
  scale_x_discrete("") +
  scale_y_continuous("Bacteroidetes/Firmicutes") +
  scale_fill_grey("Treatment", 
                  start = 0, 
                  end = 1,
                  na.value = "red",
                  aesthetics = "fill") +
  theme_bw() + 
  theme(panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(), 
        # panel.border = element_blank(), 
        axis.title.x = element_blank(),
        # axis.text.x = element_blank(),
        axis.text.x = element_text(angle = 45,
                                   hjust = 1),
        axis.ticks.x=element_blank(),
        legend.position = "top")
tiff(filename = "tmp/avg_bact_firm_nov18_may19.tiff",
     height = 4,
     width = 6,
     units = "in",
     res = 600,
     compression = "lzw+p")
print(p1)
graphics.off()
print(p1)

mufb[, est := paste0(round(mu, 2),
                     "(",
                     round(sem, 2),
                     ")")]
t1 <- dcast.data.table(mufb,
                       Genotype + Diet ~ Week,
                       value.var = "est")
datatable(t1,
          rownames = FALSE,
          caption = "Average Ratio of Bacteroidetes and Firmicutes",
          class = "cell-border stripe",
          options = list(search = FALSE,
                         pageLength = nrow(t1)))

13 Update OTU table: excuded unknown phylum and Cyanobacteria

otu <- data.table(ps0@tax_table@.Data,
                  t(ps0@otu_table@.Data))
# Remove Species mapping'
otu$Species <- NULL
dim(otu)
[1] 16221    75

14 1. Phylum

14.1 Counts at Phylum level

14.2 Relative abundance (%) at Phylum level

14.3 PCA at Phylum level

dt_pca <- t(ra_p[, 2:ncol(ra_p)])
There were 28 warnings (use warnings() to see them)
colnames(dt_pca) <- ra_p$Phylum
dt_pca_p <- data.table(Sample = rownames(dt_pca),
                       dt_pca)
dt_pca_p <- merge(smpl,
                  dt_pca_p,
                  by = "Sample")
# Keep only the phylum with non-zero counts
tmp <- dt_pca_p[, 10:ncol(dt_pca_p)]
keep_p <- colnames(tmp)[colSums(tmp) > 0]
dt_pca <- dt_pca[, keep_p]
# m1 <- prcomp(dt_pca,
#              center = TRUE,
#              scale. = TRUE)
# m1 <- prcomp(dt_pca,
#              center = FALSE,
#              scale. = FALSE)
m1 <- prcomp(dt_pca,
             center = TRUE,
             scale. = FALSE)
summary(m1)
Importance of components:
                          PC1     PC2     PC3     PC4     PC5      PC6      PC7       PC8
Standard deviation     0.1016 0.07982 0.05398 0.03765 0.01000 0.008812 0.002823 0.0004897
Proportion of Variance 0.4864 0.30051 0.13743 0.06688 0.00472 0.003660 0.000380 0.0000100
Cumulative Proportion  0.4864 0.78693 0.92435 0.99123 0.99595 0.999610 0.999990 1.0000000
                             PC9       PC10       PC11      PC12       PC13
Standard deviation     0.0001899 0.00008382 0.00003105 0.0000258 0.00002073
Proportion of Variance 0.0000000 0.00000000 0.00000000 0.0000000 0.00000000
Cumulative Proportion  1.0000000 1.00000000 1.00000000 1.0000000 1.00000000
# Select PC-s to pliot (PC1 & PC2)
choices <- 1:2
# Add meta data
dt.scr <- data.table(m1$x[, choices])
dt.scr$Sample <- rownames(m1$x)
dt.scr <- merge(smpl,
                dt.scr,
                by = "Sample")
dt.scr
# Loadings, i.e. arrows (df.v)
dt.rot <- as.data.frame(m1$rotation[, choices])
dt.rot$feat <- rownames(dt.rot)
dt.rot <- data.table(dt.rot)
dt.rot
dt.load <- melt.data.table(dt.rot,
                           id.vars = "feat",
                           measure.vars = 1:2,
                           variable.name = "pc",
                           value.name = "loading")
dt.load$feat <- factor(dt.load$feat,
                       levels = unique(dt.load$feat))
# Plot loadings
p0 <- ggplot(data = dt.load,
             aes(x = feat,
                 y = loading)) +
  facet_wrap(~ pc,
             nrow = 2) +
  geom_bar(stat = "identity") +
  ggtitle("PC Loadings") +
  theme(plot.title = element_text(hjust = 0.5),
        axis.text.x = element_text(angle = 45,
                                   hjust = 1))
p0
tiff(filename = "tmp/pc.1.2_loadings_phylum.tiff",
     height = 5,
     width = 6,
     units = 'in',
     res = 300,
     compression = "lzw+p")
print(p0)
graphics.off()
print(p0)

# Axis labels
u.axis.labs <- paste(colnames(dt.rot)[1:2], 
                     sprintf('(%0.1f%% explained var.)', 
                             100*m1$sdev[choices]^2/sum(m1$sdev^2)))
u.axis.labs
[1] "PC1 (48.6% explained var.)" "PC2 (30.1% explained var.)"
cntr <- data.table(aggregate(x = dt.scr$PC1,
                             by = list(dt.scr$Genotype),
                             FUN = "mean"),
                   aggregate(x = dt.scr$PC2,
                             by = list(dt.scr$Genotype),
                             FUN = "mean")$x)
colnames(cntr) <- c("Genotype",
                    "PC1",
                    "PC2")
# Based on Figure p0, keep only a few variables with high loadings in PC1 and PC2----
dt.rot[, rating:= (PC1)^2 + (PC2)^2]
setorder(dt.rot, -rating)
# Select top 5
dt.rot <- dt.rot[1:5, ]
# var.keep.ndx <- which(dt.rot$feat %in% c(...))
# Or select all
# var.keep.ndx <- 3:ncol(dt1)
# Use dt.rot[var.keep.ndx,] and dt.rot$feat[var.keep.ndx]
p1 <- ggplot(data = dt.rot,
             aes(x = PC1,
                 y = PC2)) +
  coord_equal() +
  geom_point(data = dt.scr,
             aes(fill = Genotype,
                 shape = factor(Timepoint)),
             size = 3,
             alpha = 0.5) +
  geom_segment(aes(x = 0,
                   y = 0,
                   xend = 0.2*PC1,
                   yend = 0.2*PC2),
               arrow = arrow(length = unit(1/2, 'picas')),
               # size = 1, 
               color = "black") +
  geom_text(aes(x = 0.22*PC1,
                y = 0.22*PC2,
                label = dt.rot$feat),
            # size = 5,
            hjust = 0.5) +
  scale_x_continuous(u.axis.labs[1]) +
  scale_y_continuous(u.axis.labs[2]) +
  scale_fill_manual(name = "Group",
                    breaks = c("Wild Type",
                               "Nrf2 KO"),
                    values = c("red",
                               "blue")) +
  scale_shape_manual(breaks = 1:3,
                     values = 21:23) +
  geom_label(data = cntr,
             aes(x = PC1,
                 y = PC2,
                 label = Genotype,
                 colour = Genotype),
             alpha = 0.5,
             size = 3) +
  scale_color_manual(guide = FALSE,
                     breaks = c("Wild Type",
                                "Nrf2 KO"),
                     values = c("red",
                                "blue")) +
  ggtitle("") +
  theme(plot.title = element_text(hjust = 0.5,
                                  size = 20),
        legend.position = "none") 
tiff(filename = "tmp/phylum_biplot_grp.tiff",
     height = 8,
     width = 8,
     units = 'in',
     res = 300,
     compression = "lzw+p")
print(p1)
graphics.off()
ggplotly(p1)
geom_GeomLabel() has yet to be implemented in plotly.
  If you'd like to see this geom implemented,
  Please open an issue with your example code at
  https://github.com/ropensci/plotly/issuesgeom_GeomLabel() has yet to be implemented in plotly.
  If you'd like to see this geom implemented,
  Please open an issue with your example code at
  https://github.com/ropensci/plotly/issues

# Generci biplot
biplot(m1)

15 2. Class

15.1 Counts at Class level

15.2 Relative abundance (%) at Class level

15.3 PCA at Class level

dt_pca <- t(ra_c[, 2:ncol(ra_c)])
colnames(dt_pca) <- ra_c$Class
dt_pca_c <- data.table(Sample = rownames(dt_pca),
                       dt_pca)
dt_pca_c <- merge(smpl,
                  dt_pca_c,
                  by = "Sample")
# Keep only the Class with non-zero counts
tmp <- dt_pca_c[, 10:ncol(dt_pca_c)]
keep_c <- colnames(tmp)[colSums(tmp) > 0]
dt_pca <- dt_pca[, keep_c]
m1 <- prcomp(dt_pca,
             center = TRUE,
             scale. = FALSE)
summary(m1)
Importance of components:
                           PC1     PC2    PC3     PC4     PC5     PC6     PC7      PC8
Standard deviation     0.08999 0.07999 0.0740 0.05046 0.03517 0.02037 0.01466 0.009891
Proportion of Variance 0.32837 0.25949 0.2220 0.10327 0.05015 0.01682 0.00872 0.003970
Cumulative Proportion  0.32837 0.58786 0.8099 0.91318 0.96333 0.98016 0.98887 0.992840
                            PC9     PC10     PC11    PC12     PC13      PC14      PC15
Standard deviation     0.008728 0.007865 0.005555 0.00265 0.000615 0.0004527 0.0001791
Proportion of Variance 0.003090 0.002510 0.001250 0.00028 0.000020 0.0000100 0.0000000
Cumulative Proportion  0.995930 0.998440 0.999690 0.99997 0.999990 1.0000000 1.0000000
                             PC16      PC17      PC18       PC19       PC20       PC21
Standard deviation     0.00008448 0.0000719 0.0000276 0.00002248 0.00002123 0.00001378
Proportion of Variance 0.00000000 0.0000000 0.0000000 0.00000000 0.00000000 0.00000000
Cumulative Proportion  1.00000000 1.0000000 1.0000000 1.00000000 1.00000000 1.00000000
                             PC22       PC23        PC24
Standard deviation     0.00001094 0.00001006 0.000009136
Proportion of Variance 0.00000000 0.00000000 0.000000000
Cumulative Proportion  1.00000000 1.00000000 1.000000000
# Select PC-s to pliot (PC1 & PC2)
choices <- 1:2
# Add meta data
dt.scr <- data.table(m1$x[, choices])
dt.scr$Sample <- rownames(m1$x)
dt.scr <- merge(smpl,
                dt.scr,
                by = "Sample")
dt.scr
# Loadings, i.e. arrows (df.v)
dt.rot <- as.data.frame(m1$rotation[, choices])
dt.rot$feat <- rownames(dt.rot)
dt.rot <- data.table(dt.rot)
dt.rot
dt.load <- melt.data.table(dt.rot,
                           id.vars = "feat",
                           measure.vars = 1:2,
                           variable.name = "pc",
                           value.name = "loading")
dt.load$feat <- factor(dt.load$feat,
                       levels = unique(dt.load$feat))
# Plot loadings
p0 <- ggplot(data = dt.load,
             aes(x = feat,
                 y = loading)) +
  facet_wrap(~ pc,
             nrow = 2) +
  geom_bar(stat = "identity") +
  ggtitle("PC Loadings") +
  theme(plot.title = element_text(hjust = 0.5),
        axis.text.x = element_text(angle = 45,
                                   hjust = 1))
p0
tiff(filename = "tmp/pc.1.2_loadings_Class.tiff",
     height = 5,
     width = 6,
     units = 'in',
     res = 300,
     compression = "lzw+p")
print(p0)
graphics.off()
print(p0)

# Axis labels
u.axis.labs <- paste(colnames(dt.rot)[1:2], 
                     sprintf('(%0.1f%% explained var.)', 
                             100*m1$sdev[choices]^2/sum(m1$sdev^2)))
u.axis.labs
[1] "PC1 (32.8% explained var.)" "PC2 (25.9% explained var.)"
cntr <- data.table(aggregate(x = dt.scr$PC1,
                             by = list(dt.scr$Genotype),
                             FUN = "mean"),
                   aggregate(x = dt.scr$PC2,
                             by = list(dt.scr$Genotype),
                             FUN = "mean")$x)
colnames(cntr) <- c("Genotype",
                    "PC1",
                    "PC2")
# Based on Figure p0, keep only a few variables with high loadings in PC1 and PC2----
dt.rot[, rating:= (PC1)^2 + (PC2)^2]
setorder(dt.rot, -rating)
# Select top 8
dt.rot <- dt.rot[1:8, ]
# var.keep.ndx <- which(dt.rot$feat %in% c(...))
# Or select all
# var.keep.ndx <- 3:ncol(dt1)
# Use dt.rot[var.keep.ndx,] and dt.rot$feat[var.keep.ndx]
p1 <- ggplot(data = dt.rot,
             aes(x = PC1,
                 y = PC2)) +
  coord_equal() +
  geom_point(data = dt.scr,
             aes(fill = Genotype,
                 shape = factor(Timepoint)),
             size = 3,
             alpha = 0.5) +
  geom_segment(aes(x = 0,
                   y = 0,
                   xend = 0.2*PC1,
                   yend = 0.2*PC2),
               arrow = arrow(length = unit(1/2, 'picas')),
               # size = 1, 
               color = "black") +
  geom_text(aes(x = 0.22*PC1,
                y = 0.22*PC2,
                label = dt.rot$feat),
            # size = 5,
            hjust = 0.5) +
  scale_x_continuous(u.axis.labs[1]) +
  scale_y_continuous(u.axis.labs[2]) +
  scale_fill_manual(name = "Group",
                    breaks = c("Wild Type",
                               "Nrf2 KO"),
                    values = c("red",
                               "blue")) +
  scale_shape_manual(breaks = 1:3,
                     values = 21:23) +
  geom_label(data = cntr,
             aes(x = PC1,
                 y = PC2,
                 label = Genotype,
                 colour = Genotype),
             alpha = 0.5,
             size = 3) +
  scale_color_manual(guide = FALSE,
                     breaks = c("Wild Type",
                                "Nrf2 KO"),
                     values = c("red",
                                "blue")) +
  ggtitle("") +
  theme(plot.title = element_text(hjust = 0.5,
                                  size = 20),
        legend.position = "none") 
tiff(filename = "tmp/class_biplot_gen.tiff",
     height = 8,
     width = 8,
     units = 'in',
     res = 300,
     compression = "lzw+p")
print(p1)
graphics.off()
ggplotly(p1)
geom_GeomLabel() has yet to be implemented in plotly.
  If you'd like to see this geom implemented,
  Please open an issue with your example code at
  https://github.com/ropensci/plotly/issuesgeom_GeomLabel() has yet to be implemented in plotly.
  If you'd like to see this geom implemented,
  Please open an issue with your example code at
  https://github.com/ropensci/plotly/issues

# Generic biplot
biplot(m1)

15.4 3. Order

15.5 4. Family

15.6 5 Geus

15.7 Counts at Genus level

15.8 Relative abundance (%) at Genus level

Error in sum(a) : invalid 'type' (character) of argument

16 Session Information

sessionInfo()
LS0tCnRpdGxlOiAiTnJmMiBCTDYgV2lsZC1UeXBlIChXVCkgUEVJVEMgMTZTIE1pY3JvYmlvbWUgRGF0YSBWaXN1YWxpemF0aW9uIgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKLS0tCkRhdGU6IGByIGRhdGUoKWAgICAgIApTY2llbnRpc3Q6IFtSYW4gWWluXShtYWlsdG86cnkxNDdAc2NhcmxldG1haWwucnV0Z2Vycy5lZHUpICAgICAgClNlcXVlbmNpbmcgKFdha3NtYW4pOiBbRGlieWVuZHUgS3VtYXJdKG1haWx0bzpka0B3YWtzbWFuLnJ1dGdlcnMuZWR1KSAgICAgIApTdGF0aXN0aWNzOiBbRGF2aXQgU2FyZ3N5YW5dKG1haWx0bzpzYXJnZGF2aWRAZ21haWwuY29tKSAgICAgIApQcmluY2lwYWwgSW52ZXN0aWdhdG9yOiBbQWgtTmcgS29uZ10obWFpbHRvOmtvbmd0QHBoYXJtYWN5LnJ1dGdlcnMuZWR1KSAKCmBgYHt9CiMgVGF4b25vbWljIFJhbmtzOgojICoqSyoqaW5nICoqUCoqaGlsbGlwICoqQyoqYW4gbioqTyoqdCAqKkYqKmluZCAqKkcqKnJlZW4gKipTKipvY2tzCiMgKiBLaW5nZG9tICAgICAgICAgICAgICAgIAojICogUGh5bHVtICAgICAgICAgICAgICAgICAgICAKIyAqIENsYXNzICAgICAgICAgICAgICAgICAgIAojICogT3JkZXIgICAgICAgICAgICAgICAgICAgCiMgKiBGYW1pbHkgICAgIAojICogR2VudXMgICAgIAojICogU3BlY2llcyAgCmBgYAoKYGBge3Igc2V0dXB9Cm9wdGlvbnMoc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFLAogICAgICAgIHNjaXBlbiA9IDk5OSkKCiMgIyBJbmNyZWFzZSBtbWVtb3J5IHNpemUgdG8gNjQgR2ItLS0tCiMgaW52aXNpYmxlKHV0aWxzOjptZW1vcnkubGltaXQoNjU1MzYpKQojIHN0cihrbml0cjo6b3B0c19jaHVuayRnZXQoKSkKIyAjIE5PVEU6IHRoZSBiZWxvdyBkb2VzIG5vdCB3b3JrIQojIGtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gRkFMU0UsIAojICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsCiMgICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwKIyAgICAgICAgICAgICAgICAgICAgICAgZXJyb3IgPSBGQUxTRSkKCiMgcmVxdWlyZShrbml0cikKIyByZXF1aXJlKGthYmxlRXh0cmEpCiMgcmVxdWlyZShzaGlueSkKCnJlcXVpcmUocGh5bG9zZXEpCnJlcXVpcmUoZGF0YS50YWJsZSkKcmVxdWlyZShnZ3Bsb3QyKQpyZXF1aXJlKHBsb3RseSkKcmVxdWlyZShEVCkKCnNvdXJjZSgic291cmNlL2Z1bmN0aW9uc19tYXkyMDE5LlIiKQoKIyBPbiBXaW5kb3dzIHNldCBtdWx0aXRocmVhZD1GQUxTRS0tLS0KbXQgPC0gVFJVRQpgYGAKCiMgSW50cm9kdWN0aW9uCk5vdmVtYmVyIDIwMTggQmF0Y2g6IE5yZjIgS08gKC0vLSkgTWljZSAgCk1heSAyMDE5IEJhdGNoOiBXaWxkIFR5cGUgTWljZSAgCgojIERhdGEgcHJlcHJvY2Vzc2luZwojIyBSYXcgRGF0YSAKRmFzdFEgZmlsZXMgd2VyZSBkb3dubG9hZGVkIGZyb20gW0RyLiBLdW1hcidzIERyb3BCb3hdKGh0dHBzOi8vd3d3LmRyb3Bib3guY29tL3NoL3NtOXRpbm0wZjVyNnkxdi9BQURqR1BSUk5pSU03ek1TZkFORGtRakZhP2RsPTApLiBBIHRvdGFsIG9mIDYwIGZpbGVzICgyIHBlciBzYW1wbGUsIHBhaXItZW5kZWQpIGFuZCAyIG1ldGFkYXRhIGZpbGVzIHdlcmUgZG93bmxvYWRlZC4KCiMjIFNjcmlwdApEYXRhIHByb2Nlc3Npbmcgc2NyaXB0cyAoKioqbnJmMnViaW9tZV9kYWRhMl9ub3YyMDE4X3YxLlJtZCoqKiBhbmQgKioqbnJmMnViaW9tZV9kYWRhMl9tYXkyMDE5X3YxLlJtZCoqKikgd2VyZSBkZXZlbG9wZWQgdXNpbmcgW0RBREEyIFBpcGVsaW5lIFR1dG9yaWFsICgxLjEyKV0oaHR0cHM6Ly9iZW5qam5lYi5naXRodWIuaW8vZGFkYTIvdHV0b3JpYWwuaHRtbCkgd2l0aCB0aXBzIGFuZCB0cmlja3MgZnJvbSB0aGUgW1VuaXZlcnNpdHkgb2YgTWFyeWxhbmQgU2hvb2wgb2YgTWVkaWNpbmUgSW5zdGl0dXRlIGZvciBHZW5vbWUgU2NpZW5jZXMgKElHUyldKGh0dHA6Ly93d3cuaWdzLnVtYXJ5bGFuZC5lZHUvKSBbTWljcm9iaW9tZSBBbmFseXNpcyBXb3Jrc2hvcCAoQXByaWwgOC0xMSwgMjAxOSldKGh0dHA6Ly93d3cuaWdzLnVtYXJ5bGFuZC5lZHUvZWR1Y2F0aW9uL3drc2hwX21ldGFnZW5vbWUucGhwKS4gVGhlIG9yZXN1bHRzIG9mIHRoZSBEQURBMiBzY3JpcHRzICgqKipkYXRhX25vdjIwMTgvcHNfbm92MjAxOC5SRGF0YSoqKiBhbmQgKioqZGF0YV9tYXkyMDE5L3BzX21heTIwMTkuUkRhdGEqKiopIGFyZSBleHBsb3JlZCBpbiB0aGlzIGRvY3VtZW50LgoKIyBNZXRhIGRhdGE6IHNhbXBsZSBkZXNjcmlwdGlvbgpgYGB7ciBkYXRhfQojIExvYWQgZGF0YS0tLS0KIyBDb3VudHMKbG9hZCgiZGF0YV9ub3YyMDE4L3BzX25vdjIwMTguUkRhdGEiKQpwc19ub3YyMDE4IDwtIGNvcHkocHMpCnJtKHBzKQojIFJlbW92ZSAiVW5kZXRlcm1pbmVkIiBzYW1wbGUKcHNfbm92MjAxOCA8LSBzdWJzZXRfc2FtcGxlcyhwc19ub3YyMDE4LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOYW1lICE9ICJVbmRldGVybWluZWRfUzAiKQoKbG9hZCgiZGF0YV9tYXkyMDE5L3BzX21heTIwMTkuUkRhdGEiKQoKZ2ModmVyYm9zZSA9IEZBTFNFKQoKIyBUYXhvbm9teSAodXNlIHRoZSBzYW1lIG9uZSBmb3IgYm90aCBiYXRjaGVzISkKbG9hZCgiZGF0YV9tYXkyMDE5L3RheGEuUkRhdGEiKQp0YXhhIDwtIGRhdGEudGFibGUoc2VxMTZzID0gcm93bmFtZXModGF4YSksCiAgICAgICAgICAgICAgICAgICB0YXhhKQoKIyBTYW1wbGVzCm1ldGExOCA8LSBwc19ub3YyMDE4QHNhbV9kYXRhCmRhdGF0YWJsZShtZXRhMTgsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChwYWdlTGVuZ3RoID0gbnJvdyhtZXRhMTgpKSwKICAgICAgICAgIGNhcHRpb24gPSAiTnJmMiBLTyAoTm92IDE4KSBNZXRhIERhdGEiKQoKbWV0YTE5IDwtIHBzX21heTIwMTlAc2FtX2RhdGEKZGF0YXRhYmxlKG1ldGExOSwKICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHBhZ2VMZW5ndGggPSBucm93KG1ldGExOSkpLAogICAgICAgICAgY2FwdGlvbiA9ICJXVCAoTWF5IDE5KSBNZXRhIERhdGEiKQpgYGAKCiMgT1RVcyBtYXBwZWQgdG8gS2luZ2RvbXMsIGVhY2ggYmF0Y2ggc2VwYXJhdGUKYGBge3IgbWFwcGluZ19raW5nZG9tX2J5X2JhdGNoLCB3YXJuaW5nID0gRkFMU0UsIGVjaG8gPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQp0MSA8LSBkYXRhLnRhYmxlKHRhYmxlKHRheF90YWJsZShwc19ub3YyMDE4KVssCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJLaW5nZG9tIl0sCiAgICAgICAgICAgICAgICAgICAgICAgZXhjbHVkZSA9IE5VTEwpKQp0MiA8LSBkYXRhLnRhYmxlKHRhYmxlKHRheF90YWJsZShwc19tYXkyMDE5KVssCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJLaW5nZG9tIl0sCiAgICAgICAgICAgICAgICAgICAgICAgZXhjbHVkZSA9IE5VTEwpKQp0dDEgPC0gbWVyZ2UodDEsCiAgICAgICAgICAgICB0MiwKICAgICAgICAgICAgIGJ5ID0gIlYxIiwKICAgICAgICAgICAgIGFsbCA9IFRSVUUpCgp0dDEkVjFbaXMubmEodHQxJFYxKV0gPC0gIlVua25vd24iCnR0MSROLnlbaXMubmEodHQxJE4ueSldIDwtIDAKCgp0dDFbLHBjdC54IDo9IE4ueC9zdW0oTi54LCBuYS5ybSA9IFRSVUUpXQp0dDFbLHBjdC55IDo9IE4ueS9zdW0oTi55LCBuYS5ybSA9IFRSVUUpXQp0dDEgPC0gdHQxW29yZGVyKHR0MSROLngsCiAgICAgICAgICAgICAgICAgZGVjcmVhc2luZyA9IFRSVUUpLCBdCgpjb2xuYW1lcyh0dDEpIDwtIGMoIktpbmdkb20iLAogICAgICAgICAgICAgICAgICAgIk51bWJlciBvZiBPVFVzIGluIE5yZjIgS08gTWljZSIsCiAgICAgICAgICAgICAgICAgICAiTnVtYmVyIG9mIE9UVXMgaW4gV1QgTWljZSIsCiAgICAgICAgICAgICAgICAgICAiUGVyY2VudCBvZiBPVFVzIGluIE5yZjIgS08gTWljZSIsCiAgICAgICAgICAgICAgICAgICAiUGVyY2VudCAgb2YgT1RVcyBpbiBXVCBNaWNlIikKCmRhdGF0YWJsZSh0dDEsCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJOdW1iZXIgb2YgT1RVcyBieSBLaW5nZG9tIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSBucm93KHQxKSkpICU+JQogIGZvcm1hdEN1cnJlbmN5KGNvbHVtbnMgPSAyOjMsCiAgICAgICAgICAgICAgICAgY3VycmVuY3kgPSAiIiwKICAgICAgICAgICAgICAgICBtYXJrID0gIiwiLAogICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDApICU+JQogIGZvcm1hdFBlcmNlbnRhZ2UoY29sdW1ucyA9IDQ6NSwKICAgICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDIpCmBgYAoKIyBNZXJnZSB0aGUgMiBkYXRhIHNldHMKYGBge3IgbWVyZ2VfYmF0Y2hlc30KcHNzIDwtIG1lcmdlX3BoeWxvc2VxKHBzX25vdjIwMTgsCiAgICAgICAgICAgICAgICAgICAgICBwc19tYXkyMDE5KQp0bXAgPC0gcHNzQHNhbV9kYXRhCgojIERpZXQKbWV0YSA8LSBkYXRhLnRhYmxlKFNhbXBsZSA9IHJvd25hbWVzKHBzc0BzYW1fZGF0YSksCiAgICAgICAgICAgICAgICAgICBEaWV0ID0gdG1wJERpZXQpCm1ldGEkRGlldCA8LSBnc3ViKHggPSBtZXRhJERpZXQsIAogICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gIiBDb250cm9sIiwKICAgICAgICAgICAgICAgICAgcmVwbGFjZW1lbnQgPSAiIikKbWV0YSREaWV0WyFpcy5uYSh0bXAkVFJFQVRNRU5UKV0gPC0gdG1wJFRSRUFUTUVOVFshaXMubmEodG1wJFRSRUFUTUVOVCldCm1ldGEkRGlldCA8LSBnc3ViKHggPSBtZXRhJERpZXQsCiAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiQ29udHJvbCIsCiAgICAgICAgICAgICAgICAgIHJlcGxhY2VtZW50ID0gIkFJTjkzTSIpCm1ldGEkRGlldFtpcy5uYShtZXRhJERpZXQpXSA8LSAiUG9vbGVkIgptZXRhJERpZXQgPC0gZmFjdG9yKG1ldGEkRGlldCwKICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJBSU45M00iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBFSVRDIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJQb29sZWQiKSkKCiMgR2Vtb3R5cGUKbWV0YSRHZW5vdHlwZSA8LSAiTnJmMiBLTyIKbWV0YSRHZW5vdHlwZVtpcy5uYSh0bXAkU2V4KV0gPC0gIldpbGQgVHlwZSIKbWV0YSRHZW5vdHlwZSA8LSBmYWN0b3IobWV0YSRHZW5vdHlwZSwKICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiV2lsZCBUeXBlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTnJmMiBLTyIpKQoKIyBUaW1lCm1ldGEkV2VlayA8LSBhcy5udW1lcmljKGFzLmNoYXJhY3Rlcih0bXAkV2VlaykpIC0gNAptZXRhJFdlZWtbbWV0YSRHZW5vdHlwZSA9PSAiV2lsZCBUeXBlIl0gPC0gYXMubnVtZXJpYyhnc3ViKHggPSB0bXAkV0VFS1ttZXRhJEdlbm90eXBlID09ICJXaWxkIFR5cGUiXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gIndlZWsgIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXBsYWNlbWVudCA9ICIiKSkKbWV0YSRXZWVrIDwtIHBhc3RlKCJXZWVrIiwKICAgICAgICAgICAgICAgICAgIG1ldGEkV2VlaykKbWV0YSRXZWVrIDwtIGZhY3RvcihtZXRhJFdlZWssCiAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiV2VlayAwIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJXZWVrIDEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIldlZWsgNCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiV2VlayA1IikpCgojIE1vdXNlIElECm1ldGEkTW91c2VfTnVtIDwtIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKHRtcCRNb3VzZU51bSkpCm1ldGEkTW91c2VfTnVtW21ldGEkR2Vub3R5cGUgPT0gIldpbGQgVHlwZSJdIDwtIGFzLm51bWVyaWMoc3Vic3RyKHggPSB0bXAkU0FNUExFX05BTUVbbWV0YSRHZW5vdHlwZSA9PSAiV2lsZCBUeXBlIl0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0ID0gMywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0b3AgPSAzKSkKCiMgQ2FnZSBudW1iZXIKbWV0YSRDYWdlIDwtIGFzLmNoYXJhY3Rlcih0bXAkQ2FnZSkKbWV0YSRDYWdlW21ldGEkR2Vub3R5cGUgPT0gIldpbGQgVHlwZSJdIDwtIHN1YnN0cih4ID0gdG1wJFNBTVBMRV9OQU1FW21ldGEkR2Vub3R5cGUgPT0gIldpbGQgVHlwZSJdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0ID0gMiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RvcCA9IDIpCm1ldGEkQ2FnZSA8LSBmYWN0b3IobWV0YSRDYWdlKQoKbWV0YSA8LSBkYXRhLmZyYW1lKG1ldGEpCnJvd25hbWVzKG1ldGEpIDwtIG1ldGEkU2FtcGxlCm1ldGEKCiMgRWRpdCBtZXRhIGRhdGEKc2FtcGxlX2RhdGEocHNzKSA8LSBtZXRhCnBzc0BzYW1fZGF0YQpgYGAKCmBgYHtyIG1hcHBpbmdfa2luZ2RvbV9jb21iaW5lZCwgd2FybmluZyA9IEZBTFNFLCBlY2hvID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRX0KdDEgPC0gZGF0YS50YWJsZSh0YWJsZSh0YXhfdGFibGUocHNzKVssCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIktpbmdkb20iXSwKICAgICAgICAgICAgICAgICAgICAgICBleGNsdWRlID0gTlVMTCkpCnQxJFYxW2lzLm5hKHQxJFYxKV0gPC0gIlVua25vd24iCgp0MVssIHBjdCA6PSBOL3N1bShOKV0Kc2V0b3JkZXIodDEsIC1OKQoKY29sbmFtZXModDEpIDwtIGMoIktpbmdkb20iLAogICAgICAgICAgICAgICAgICAiTnVtYmVyIG9mIE9UVXMiLAogICAgICAgICAgICAgICAgICAiUGVyY2VudCBvZiBPVFVzIikKZGF0YXRhYmxlKHQxLAogICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSwKICAgICAgICAgIGNhcHRpb24gPSAiTnVtYmVyIG9mIE9UVXMgYnkgS2luZ2RvbSIsCiAgICAgICAgICBjbGFzcyA9ICJjZWxsLWJvcmRlciBzdHJpcGUiLAogICAgICAgICAgb3B0aW9ucyA9IGxpc3Qoc2VhcmNoID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlTGVuZ3RoID0gbnJvdyh0MSkpKSAlPiUKICBmb3JtYXRDdXJyZW5jeShjb2x1bW5zID0gMiwKICAgICAgICAgICAgICAgICBjdXJyZW5jeSA9ICIiLAogICAgICAgICAgICAgICAgIG1hcmsgPSAiLCIsCiAgICAgICAgICAgICAgICAgZGlnaXRzID0gMCkgJT4lCiAgZm9ybWF0UGVyY2VudGFnZShjb2x1bW5zID0gMywKICAgICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDIpCmBgYAoKYGBge3Iga2VlcF9iYWN0ZXJpYX0KZGltKHBzc0BvdHVfdGFibGVALkRhdGEpCgojIFJlbW92ZSBPVFUgdW5tYXBwZWQgdG8gQmFjdGVyaWEKcHMwIDwtIHN1YnNldF90YXhhKHBzcywgCiAgICAgICAgICAgICAgICAgICBLaW5nZG9tID09ICJCYWN0ZXJpYSIpCmRpbShwczBAb3R1X3RhYmxlQC5EYXRhKQpgYGAKCiMgT1RVIHRhYmxlIChmaXJzdCAxMCByb3dzKQpgYGB7ciBvdHVfdGFibGUsIHdhcm5pbmc9RkFMU0UsZWNobz1GQUxTRSxtZXNzYWdlPUZBTFNFfQpvdHUgPC0gZGF0YS50YWJsZShwczBAdGF4X3RhYmxlQC5EYXRhLAogICAgICAgICAgICAgICAgICB0KHBzMEBvdHVfdGFibGVALkRhdGEpKQoKIyBSZW1vdmUgU3BlY2llcyBtYXBwaW5nJwpvdHUkU3BlY2llcyA8LSBOVUxMCgpkYXRhdGFibGUoaGVhZChvdHUsIDEwKSwKICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgICBjYXB0aW9uID0gIlRheG9ub21pYyAgY291bnQgdGFibGUiLAogICAgICAgICAgY2xhc3MgPSAiY2VsbC1ib3JkZXIgc3RyaXBlIiwKICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNlYXJjaCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IDEwKSkgJT4lCiAgZm9ybWF0Q3VycmVuY3koY29sdW1ucyA9IDc6MzYsCiAgICAgICAgICAgICAgICAgY3VycmVuY3kgPSAiIiwKICAgICAgICAgICAgICAgICBtYXJrID0gIiwiLAogICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDApCmBgYAoKIyBUb3RhbCBjb3VudHMgcGVyIHNhbXBsZSAoaS5lLiBzZXF1ZW5jaW5nIGRlcHRoKQpgYGB7ciBzZXFfZGVwdGhfcGxvdGx5LCB3YXJuaW5nPUZBTFNFLGVjaG89RkFMU0UsbWVzc2FnZT1GQUxTRSxmaWcud2lkdGg9MTAsZmlnLmhlaWdodD01fQp0MSA8LSBjb2xTdW1zKG90dVssIDc6bmNvbChvdHUpXSkKdDEgPC0gZGF0YS50YWJsZShTYW1wbGUgPSBuYW1lcyh0MSksCiAgICAgICAgICAgICAgICAgVG90YWwgPSB0MSkKCnNtcGwgPC0gbWVyZ2UobWV0YSwKICAgICAgICAgICAgICB0MSwKICAgICAgICAgICAgICBieSA9ICJTYW1wbGUiKQoKcDEgPC0gZ2dwbG90KHNtcGwsCiAgICAgICAgICAgICBhZXMoeCA9IFNhbXBsZSwKICAgICAgICAgICAgICAgICB5ID0gVG90YWwsCiAgICAgICAgICAgICAgICAgZmlsbCA9RGlldCwKICAgICAgICAgICAgICAgICBjb2xvdXIgPSBXZWVrKSkgKwogIGZhY2V0X3dyYXAofiBHZW5vdHlwZSwKICAgICAgICAgICAgIHNjYWxlID0gImZyZWUiKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBzY2FsZV94X2Rpc2NyZXRlKCJTYW1wbGUgTmFtZSIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoIk51bWJlciBvZiBSZWFkcyIpICsKICBzY2FsZV9maWxsX2Rpc2NyZXRlKCJHcm91cCIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gMSkpIApnZ3Bsb3RseShwMSkKYGBgCgpgYGB7ciBzZXFfZGVwdGhfZ3JleXNjYWxlLCBmaWcuaGVpZ2h0ID0gNiAsIGZpZy53aWR0aCA9OH0KcDEgPC0gZ2dwbG90KHNtcGwsCiAgICAgICAgICAgICBhZXMoeCA9IFNhbXBsZSwKICAgICAgICAgICAgICAgICB5ID0gVG90YWwsCiAgICAgICAgICAgICAgICAgZ3JvdXAgPURpZXQsCiAgICAgICAgICAgICAgICAgZmlsbCA9IERpZXQpKSArCiAgZmFjZXRfd3JhcCh+IEdlbm90eXBlICsgV2VlaywKICAgICAgICAgICAgIHNjYWxlID0gImZyZWUiKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsCiAgICAgICAgICAgY29sb3IgPSAiYmxhY2siKSArCiAgc2NhbGVfeF9kaXNjcmV0ZSgiIikgKwogIHNjYWxlX3lfY29udGludW91cygiTnVtYmVyIG9mIFJlYWRzIikgKwogIHNjYWxlX2ZpbGxfZ3JleSgiVHJlYXRtZW50IiwgCiAgICAgICAgICAgICAgICAgIHN0YXJ0ID0gMC4xLCAKICAgICAgICAgICAgICAgICAgZW5kID0gMSwKICAgICAgICAgICAgICAgICAgbmEudmFsdWUgPSAicmVkIiwKICAgICAgICAgICAgICAgICAgYWVzdGhldGljcyA9ICJmaWxsIikgKwogIHRoZW1lX2J3KCkgKyAKICB0aGVtZShwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICMgYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IDEpLAogICAgICAgICMgYXhpcy50aWNrcy54PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIikKCnRpZmYoZmlsZW5hbWUgPSAidG1wL3NlcV9kZXB0aF9ub3YyMDE4X21heTIwMTkudGlmZiIsCiAgICAgaGVpZ2h0ID02LAogICAgIHdpZHRoID0gOCwKICAgICB1bml0cyA9ICJpbiIsCiAgICAgcmVzID0gNjAwLAogICAgIGNvbXByZXNzaW9uID0gImx6dytwIikKcHJpbnQocDEpCmdyYXBoaWNzLm9mZigpCgpwcmludChwMSkKYGBgCgoKYGBge3IgcGh5bHVtX21hcHBpbmd9CnQyIDwtIGRhdGEudGFibGUodGFibGUodGF4X3RhYmxlKHBzMClbLCAiUGh5bHVtIl0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGNsdWRlID0gTlVMTCkpCnQyJFYxW2lzLm5hKHQyJFYxKV0gPC0gIlVua25vd24iCnNldG9yZGVyKHQyLCAtTikKdDJbLCBwY3QgOj0gTi9zdW0oTildCnNldG9yZGVyKHQyLCAtTikKCmNvbG5hbWVzKHQyKSA8LSBjKCJQaHlsdW0iLAogICAgICAgICAgICAgICAgICAiTnVtYmVyIG9mIE9UVXMiLAogICAgICAgICAgICAgICAgICAiUGVyY2VudCBvZiBPVFVzIikKCmRhdGF0YWJsZSh0MiwKICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgICBjYXB0aW9uID0gIk51bWJlciBvZiBCYWN0ZXJpYWwgT1RVcyBieSBQaHlsdW0iLAogICAgICAgICAgY2xhc3MgPSAiY2VsbC1ib3JkZXIgc3RyaXBlIiwKICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNlYXJjaCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IG5yb3codDIpKSkgJT4lCiAgZm9ybWF0Q3VycmVuY3koY29sdW1ucyA9IDIsCiAgICAgICAgICAgICAgICAgY3VycmVuY3kgPSAiIiwKICAgICAgICAgICAgICAgICBtYXJrID0gIiwiLAogICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDApICU+JQogIGZvcm1hdFBlcmNlbnRhZ2UoY29sdW1ucyA9IDMsCiAgICAgICAgICAgICAgICAgICBkaWdpdHMgPSAyKQoKcHMxIDwtIHN1YnNldF90YXhhKHBzMCwgCiAgICAgICAgICAgICAgICAgICAhaXMubmEoUGh5bHVtKSkKZGltKHBzMUBvdHVfdGFibGVALkRhdGEpCmBgYAoKIyBSZW1vdmUgUGh5bHVtClJlbW92ZTogIAoxLiBVbm1hcHBlZCBPVFVzICgiVW5rbm93biIpLiAgICAKMi4gQ3lhbm9iYWN0ZXJpYTogYWVyb2JpYywgcGhvdG9zeW50aGVzaXppbmcgIGJhY3RlcmlhIHRoYXQgcHJvYmFibHkgZ290IGludG8gdGhlIHNhbXBsZSB0aHJvdWdoIGZvb2QuICAKTk9URTogW0NobG9yb2ZsZXhpIG1pZ2h0IGJlIG9rLl0oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9wbWMvYXJ0aWNsZXMvUE1DNDE5Mjg0MC8pICAKICAKYGBge3IgcmVtb3ZlX3BoeWx1bXN9CnBzMCA8LSBzdWJzZXRfdGF4YShwczAsCiAgICAgICAgICAgICAgICAgICAoUGh5bHVtICVpbiUgYygiVW5rbm93biIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkN5YW5vYmFjdGVyaWEiKSkpCmBgYAoKIyBSaWNobmVzcyAoQWxwaGEgZGl2ZXJzaXR5KQpTaGFubm9uIGluZGV4IChha2EgU2hhbm5vbiBlbnRocm9waHkpIGlzIGNhbGN1bGF0ZWQgYXM6ICAKSCcgPSAtc3VtKDEgdG8gUilwKGkpbG4ocChpKSkgCldoZW4gdGhlcmUgaXMgZXhhY3RseSAxIHR5cGUgb2YgZGF0YSAoZS5nLiBhIHNpbmdsZSBzcGVjaWVzIGluIHRoZSBzYW1wbGUpLCBIJz0wLiBUaGUgb3Bwb3NpdGUgc2NlbmFyaW8gaXMgd2hlbiB0aGVyZSBhcmUgUj4xIHNwZWNpZXMgcHJlc2VudCBpbiB0aGUgc2FtcGxlIGluIHRoZSBleGFjdCBzYW1lIGFtb3VudHMgYW5kIEgnPWxuKFIpLiAgCiAgClNoYW5ub24ncyBkaXZlcnNpdHkgaW5kZXggd2FzIGNhbGN1bGF0ZWQgZm9yIGVhY2ggc2FtcGxlIGFuZCBwbG90ZWQgb3ZlciB0aW1lLgoKYGBge3Igc2hhbm5vbl92c19kZXB0aCwgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aCA9IDZ9CnNoYW5ub24ubmR4IDwtIGVzdGltYXRlX3JpY2huZXNzKHBzMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVhc3VyZXMgPSAiU2hhbm5vbiIpCgpzaGFubm9uLm5keCA8LSBkYXRhLnRhYmxlKFNhbXBsZSA9IHJvd25hbWVzKHNoYW5ub24ubmR4KSwKICAgICAgICAgICAgICAgICAgICAgICAgICBzaGFubm9uLm5keCkKCnNtcGwgPC0gbWVyZ2Uoc21wbCwKICAgICAgICAgICAgICBzaGFubm9uLm5keCwKICAgICAgICAgICAgICBieSA9ICJTYW1wbGUiKQoKcDEgPC0gZ2dwbG90KHNtcGwsCiAgICAgICAgICAgICBhZXMoeCA9IFRvdGFsLAogICAgICAgICAgICAgICAgIHkgPSBTaGFubm9uLAogICAgICAgICAgICAgICAgIGZpbGwgPSBHZW5vdHlwZSwKICAgICAgICAgICAgICAgICBzaGFwZSA9IFdlZWspKSArCiAgZ2VvbV9wb2ludChzaXplID0gMikgKwogIHNjYWxlX3NoYXBlX21hbnVhbChicmVha3MgPSB1bmlxdWUoc21wbCRXZWVrKSwKICAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gMjE6MjQpCgp0aWZmKGZpbGVuYW1lID0gInRtcC9zaGFubm9uX3ZzX2RlcHRoX25vdjE4X21heTE5LnRpZmYiLAogICAgIGhlaWdodCA9IDUsCiAgICAgd2lkdGggPSA2LAogICAgIHVuaXRzID0gImluIiwKICAgICByZXMgPSA2MDAsCiAgICAgY29tcHJlc3Npb24gPSAibHp3K3AiKQpwcmludChwMSkKZ3JhcGhpY3Mub2ZmKCkKCmdncGxvdGx5KHAxKQpgYGAKCkV2ZW4gdGhvdWdoICoqKmVzdGltYXRlX3JpY2huZXNzKioqIGZ1bmN0aW9uIGRvZXMgbm90IGFkanVzdCBmb3IgdGhlIHNlcXVlbmNpbmcgZGVwdGgsIHRoZXJlIGlzIG5vIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlIGluZGV4IGFuZCB0aGUgc2FtcGxlJ3Mgc2VxdWVjaW5nIGRlcHRoLiBQcm9jZWVkIHdpdGggdGhlIGNvbXBhcmlzb24uCgojIFNoYW5ub24gaWRleCBvdmVyIHRpbWUKYGBge3IgcmljaG5lc3MsIGZpZy5oZWlnaHQgPSA1LCBmaWcud2lkdGggPSA4fQpwMSA8LSBwbG90X3JpY2huZXNzKHBzMCwKICAgICAgICAgICAgICAgICAgICB4ID0gIldlZWsiLCAKICAgICAgICAgICAgICAgICAgICBtZWFzdXJlcyA9ICJTaGFubm9uIikgKwogIGZhY2V0X3dyYXAofiBHZW5vdHlwZSwKICAgICAgICAgICAgIHNjYWxlID0gImZyZWVfeCIpICsKICBnZW9tX2xpbmUoYWVzKGdyb3VwID0gcGFzdGUwKERpZXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDYWdlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTW91c2VfTnVtKSksCiAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIikgKwogIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBEaWV0KSwKICAgICAgICAgICAgIHNoYXBlID0gMjEsCiAgICAgICAgICAgICBzaXplID0gMywKICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIikgKwogIHNjYWxlX3hfZGlzY3JldGUoIiIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDMwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhqdXN0ID0gMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2anVzdCA9IDEpKQoKZ2dwbG90bHkocCA9IHAxLAogICAgICAgICB0b29sdGlwID0gYygiTW91c2VfTnVtIiwKICAgICAgICAgICAgICAgICAgICAgInZhbHVlIikpCgpwMSA8LSBwMSArIAogIHNjYWxlX2ZpbGxfZGlzY3JldGUoIiIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikKCnRpZmYoZmlsZW5hbWUgPSAidG1wL3NoYW5ub25fbm92MThfbWF5MTkudGlmZiIsCiAgICAgaGVpZ2h0ID0gNSwKICAgICB3aWR0aCA9IDgsCiAgICAgdW5pdHMgPSAiaW4iLAogICAgIHJlcyA9IDYwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCnByaW50KHAxKQpncmFwaGljcy5vZmYoKQpgYGAKClRoZSBwbG90IGFib3ZlIHN1Z2dlc3RzIHRoYXQgdGhlIGxhcmdlc3QgZGlmZmVyZW5jZXMgaW4gYWxwaGEgZGl2ZXJzaXR5IChhcyBtZWFzdXJlZCBieSBTaGFubm9uJ3MgaW5kZXgpIGFyZSBpbiBnZW5vdHlwZS4gVEhpcyB3YXMgYWxzbyBjb25maXJtZWQgaW4gdGhlIDNyZCBzdHVkeSAoU2VwdGVtYmVyIDIwMTkgYmF0Y2gpCgojIEF2ZXJhZ2UgU2hhbm5vbiBJbmRleApgYGB7ciBhdmdfc2hhbm5vbl9wbG90LCBmaWcuaGVpZ2h0ID0gNCwgZmlnLndpZHRoID0gNn0KIyBBdmVyYWdlIHNoYW5ub24gaW5kZXggYnkgdHJlYXRtZW50IGdyb3VwCnRtcCA8LSBkYXRhLnRhYmxlKGNvcHkoc21wbCkpCgp0bXBbLCBtdSA6PSBtZWFuKFNoYW5ub24pLAogICAgYnkgPSBsaXN0KERpZXQsCiAgICAgICAgICAgICAgR2Vub3R5cGUsCiAgICAgICAgICAgICAgV2VlayldCnRtcFssIHNlbSA6PSBzZChTaGFubm9uKS9zcXJ0KC5OKSwKICAgIGJ5ID0gbGlzdChEaWV0LAogICAgICAgICAgICAgIEdlbm90eXBlLAogICAgICAgICAgICAgIFdlZWspXQp0bXAgPC0gdW5pcXVlKHRtcFssIGMoIkRpZXQiLAogICAgICAgICAgICAgICAgICAgICAgIkdlbm90eXBlIiwKICAgICAgICAgICAgICAgICAgICAgICJXZWVrIiwKICAgICAgICAgICAgICAgICAgICAgICJtdSIsCiAgICAgICAgICAgICAgICAgICAgICAic2VtIildKQoKcDEgPC0gZ2dwbG90KHRtcCwKICAgICAgICAgICAgIGFlcyh4ID0gV2VlaywKICAgICAgICAgICAgICAgICB5ID0gbXUsCiAgICAgICAgICAgICAgICAgeW1pbiA9IG11IC0gc2VtLAogICAgICAgICAgICAgICAgIHltYXggPSBtdSArIHNlbSwKICAgICAgICAgICAgICAgICBmaWxsID0gRGlldCwKICAgICAgICAgICAgICAgICBncm91cCA9IERpZXQpKSArCiAgZmFjZXRfd3JhcCh+IEdlbm90eXBlLAogICAgICAgICAgICAgc2NhbGUgPSAiZnJlZV94IikgKwogIGdlb21fZXJyb3JiYXIocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjMpLAogICAgICAgICAgICAgICAgd2lkdGggPSAwLjQpICsKICBnZW9tX2xpbmUocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjMpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMywKICAgICAgICAgICAgIHNoYXBlID0gMjEsCiAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuMykpICsKICBzY2FsZV94X2Rpc2NyZXRlKCIiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKCJTaGFubm9uIEluZGV4IikgKwogIHNjYWxlX2ZpbGxfZ3JleSgiVHJlYXRtZW50IiwgCiAgICAgICAgICAgICAgICAgIHN0YXJ0ID0gMCwgCiAgICAgICAgICAgICAgICAgIGVuZCA9IDEsCiAgICAgICAgICAgICAgICAgIG5hLnZhbHVlID0gInJlZCIsCiAgICAgICAgICAgICAgICAgIGFlc3RoZXRpY3MgPSAiZmlsbCIpICsKICB0aGVtZV9idygpICsgCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLCAKICAgICAgICAjIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICMgYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoanVzdCA9IDEpLAogICAgICAgIGF4aXMudGlja3MueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIpCgp0aWZmKGZpbGVuYW1lID0gInRtcC9hdmdfc2hhbm5vbl9ub3YxOF9tYXkxOS50aWZmIiwKICAgICBoZWlnaHQgPSA0LAogICAgIHdpZHRoID0gNiwKICAgICB1bml0cyA9ICJpbiIsCiAgICAgcmVzID0gNjAwLAogICAgIGNvbXByZXNzaW9uID0gImx6dytwIikKcHJpbnQocDEpCmdyYXBoaWNzLm9mZigpCgpwcmludChwMSkKYGBgCgpOT1RFOiBjYW5ub3QgdGVzdCBkaWV0IGVmZmVjdCBiZWNhdXNlIG9mIHVuYXNzaWdlbmQgcG9vbGVkIHNhbXBsZXMgaW4gdGhlIEtPIG1pY2UuIEZvciB0aGUgc2FtZSByZWFzb24sIGNhbm5vdCB1c2UgbWl4ZWQgZWZmZWN0cyBtb2RlbCBvbiB0aGUgd2hvbGUgZGF0YSBzZXQuIEF0IGJlc3QsIHRlc3RpbmcgZ2Vub3R5cGUgYW5kIHRpbWUgdHJlbmQgYnkgYXNzdW1pbmcgV2VlayA0IGluIFdUID0gV2VlayA1IGluIEtPLgpgYGB7ciB0ZXN0X3JpY2huZXNzfQpzbXBsJFRpbWVwb2ludCA8LSBhcy5udW1lcmljKHNtcGwkV2VlaykKc21wbCRUaW1lcG9pbnRbc21wbCRUaW1lcG9pbnQgPT0gNF0gPC0gMwoKbTEgPC0gbG0oU2hhbm5vbiB+IFRpbWVwb2ludCpHZW5vdHlwZSwKICAgICAgICAgZGF0YSA9IHNtcGwpCnN1bW1hcnkobTEpCmBgYAoKTm8gc2lnbmlmaWNhbnQgdGltZSB0cmVuZDsgc2lnbmlmaWNhbnRseSBoaWdoZXIgYWxwaGEgZGl2ZXJzaXR5IGluIHRoZSBOcmYyIEtPIG1pY2UuIFRoaXMgaXMgcG9zc2libHkgYSBiYXRjaCBlZmZlY3QgYnV0IHdlIG9ic2VydmVkIHNhbWUgdHJlbmQgaW4gU3R1ZHkgMyAoQ3JhYmJlcnkgYW5kIFBFSVRDIHdpdGggYm90aCBnZW5vdHlwZXMgaW4gdGhlIHNhbWUgc3R1ZHkpLgoKIyBCYWN0ZXJpb3RpZGVzIHZzLiBGaXJtaWN1dGVzCmBgYHtyIGJhY3RfdnNfZmlybSwgZmlnLmhlaWdodCA9IDYsIGZpZy53aWR0aCA9IDgsIHdhcm5pbmcgPSBGQUxTRX0KY291bnRzX3AgPC0gY291bnRzX2J5X3RheF9yYW5rKGR0MSA9IG90dSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFnZ3JfYnkgPSAiUGh5bHVtIikKCmZiIDwtIHQoY291bnRzX3BbUGh5bHVtICVpbiUgYygiQmFjdGVyb2lkZXRlcyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRmlybWljdXRlcyIpLCAtMV0pCmZiIDwtIGRhdGEudGFibGUoU2FtcGxlID0gcm93bmFtZXMoZmIpLAogICAgICAgICAgICAgICAgIEJhY3Rlcm9pZGV0ZXMgPSBmYlssIDFdLAogICAgICAgICAgICAgICAgIEZpcm1pY3V0ZXMgPSBmYlssIDJdKQpmYiA8LSBkYXRhLnRhYmxlKG1lcmdlKG1ldGEsCiAgICAgICAgICAgIGZiLAogICAgICAgICAgICBieSA9ICJTYW1wbGUiKSkKCnAxIDwtIGdncGxvdChmYiwKICAgICAgICAgICAgIGFlcyh4ID0gbG9nMihCYWN0ZXJvaWRldGVzKSwKICAgICAgICAgICAgICAgICB5ID0gbG9nMihGaXJtaWN1dGVzKSwKICAgICAgICAgICAgICAgICBmaWxsID0gR2Vub3R5cGUpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMiwKICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiwKICAgICAgICAgICAgIHNoYXBlID0gMjEpCgpwMiA8LSBnZ3Bsb3QoZmIsCiAgICAgICAgICAgICBhZXMoeCA9IGxvZzIoQmFjdGVyb2lkZXRlcyksCiAgICAgICAgICAgICAgICAgeSA9IGxvZzIoRmlybWljdXRlcyksCiAgICAgICAgICAgICAgICAgZmlsbCA9IFdlZWspKSArCiAgZ2VvbV9wb2ludChzaXplID0gMiwKICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiwKICAgICAgICAgICAgIHNoYXBlID0gMjEpCnAzIDwtIGdncGxvdChmYiwKICAgICAgICAgICAgIGFlcyh4ID0gbG9nMihCYWN0ZXJvaWRldGVzKSwKICAgICAgICAgICAgICAgICB5ID0gbG9nMihGaXJtaWN1dGVzKSwKICAgICAgICAgICAgICAgICBmaWxsID0gRGlldCkpICsKICBnZW9tX3BvaW50KHNpemUgPSAyLAogICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siLAogICAgICAgICAgICAgc2hhcGUgPSAyMSkKCnA0IDwtIGdncGxvdChmYiwKICAgICAgICAgICAgIGFlcyh4ID0gV2VlaywKICAgICAgICAgICAgICAgICB5ID0gQmFjdGVyb2lkZXRlcy9GaXJtaWN1dGVzLAogICAgICAgICAgICAgICAgIGZpbGwgPSBEaWV0LAogICAgICAgICAgICAgICAgIGdyb3VwID0gcGFzdGUwKERpZXQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDYWdlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTW91c2VfTnVtKSkpICsKICBmYWNldF9ncmlkKH4gR2Vub3R5cGUsCiAgICAgICAgICAgICBzY2FsZSA9ICJmcmVlX3giKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMSwKICAgICAgICAgICAgIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICBnZW9tX2xpbmUocG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSgwLjMpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMiwKICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiwKICAgICAgICAgICAgIHNoYXBlID0gMjEsCiAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuMykpICArCiAgdGhlbWVfYncoKSArIAogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgIyBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAjIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAxKSwKICAgICAgICBheGlzLnRpY2tzLng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKQoKdGlmZihmaWxlbmFtZSA9ICJ0bXAvYmFjdF92c19maXJtX25vdjE4X21heTE5LnRpZmYiLAogICAgIGhlaWdodCA9IDYsCiAgICAgd2lkdGggPTgsCiAgICAgdW5pdHMgPSAiaW4iLAogICAgIHJlcyA9IDYwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCmdyaWRFeHRyYTo6Z3JpZC5hcnJhbmdlKHAxLCBwMiwgcDMsIHA0KQpncmFwaGljcy5vZmYoKQoKZ3JpZEV4dHJhOjpncmlkLmFycmFuZ2UocDEsIHAyLCBwMywgcDQpCmBgYAoKYGBge3IgYXZnX2JhY3RfZmlybSwgZmlnLmhlaWdodCA9IDQsIGZpZy53aWR0aCA9IDZ9CmZiWywgbXUgOj0gbWVhbihCYWN0ZXJvaWRldGVzL0Zpcm1pY3V0ZXMpLAogICBieSA9IGMoIkRpZXQiLAogICAgICAgICAgIkdlbm90eXBlIiwKICAgICAgICAgICJXZWVrIildCmZiWywgc2VtIDo9IHNkKEJhY3Rlcm9pZGV0ZXMvRmlybWljdXRlcykvc3FydCguTiksCiAgIGJ5ID0gYygiRGlldCIsCiAgICAgICAgICAiR2Vub3R5cGUiLAogICAgICAgICAgIldlZWsiKV0KCm11ZmIgPC0gdW5pcXVlKGZiWywgYygiRGlldCIsCiAgICAgICAgICAgICAgICAgICAgICAiR2Vub3R5cGUiLAogICAgICAgICAgICAgICAgICAgICAgIldlZWsiLAogICAgICAgICAgICAgICAgICAgICAgIm11IiwKICAgICAgICAgICAgICAgICAgICAgICJzZW0iKV0pCgpwMSA8LSBnZ3Bsb3QobXVmYiwKICAgICAgICAgICAgIGFlcyh4ID0gV2VlaywKICAgICAgICAgICAgICAgICB5ID0gbXUsCiAgICAgICAgICAgICAgICAgeW1pbiA9IG11IC0gc2VtLAogICAgICAgICAgICAgICAgIHltYXggPSBtdSArIHNlbSwKICAgICAgICAgICAgICAgICBmaWxsID0gRGlldCwKICAgICAgICAgICAgICAgICBncm91cCA9IERpZXQpKSArCiAgZmFjZXRfd3JhcCh+IEdlbm90eXBlLAogICAgICAgICAgICAgc2NhbGUgPSAiZnJlZV94IikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDEsCiAgICAgICAgICAgICBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgZ2VvbV9lcnJvcmJhcihwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuMyksCiAgICAgICAgICAgICAgICB3aWR0aCA9IDAuNCkgKwogIGdlb21fbGluZShwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKDAuMykpICsKICBnZW9tX3BvaW50KHNpemUgPSAzLAogICAgICAgICAgICAgc2hhcGUgPSAyMSwKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2UoMC4zKSkgKwogIHNjYWxlX3hfZGlzY3JldGUoIiIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoIkJhY3Rlcm9pZGV0ZXMvRmlybWljdXRlcyIpICsKICBzY2FsZV9maWxsX2dyZXkoIlRyZWF0bWVudCIsIAogICAgICAgICAgICAgICAgICBzdGFydCA9IDAsIAogICAgICAgICAgICAgICAgICBlbmQgPSAxLAogICAgICAgICAgICAgICAgICBuYS52YWx1ZSA9ICJyZWQiLAogICAgICAgICAgICAgICAgICBhZXN0aGV0aWNzID0gImZpbGwiKSArCiAgdGhlbWVfYncoKSArIAogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgICAgICAgIyBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksIAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAjIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAxKSwKICAgICAgICBheGlzLnRpY2tzLng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKQoKdGlmZihmaWxlbmFtZSA9ICJ0bXAvYXZnX2JhY3RfZmlybV9ub3YxOF9tYXkxOS50aWZmIiwKICAgICBoZWlnaHQgPSA0LAogICAgIHdpZHRoID0gNiwKICAgICB1bml0cyA9ICJpbiIsCiAgICAgcmVzID0gNjAwLAogICAgIGNvbXByZXNzaW9uID0gImx6dytwIikKcHJpbnQocDEpCmdyYXBoaWNzLm9mZigpCgpwcmludChwMSkKCm11ZmJbLCBlc3QgOj0gcGFzdGUwKHJvdW5kKG11LCAyKSwKICAgICAgICAgICAgICAgICAgICAgIigiLAogICAgICAgICAgICAgICAgICAgICByb3VuZChzZW0sIDIpLAogICAgICAgICAgICAgICAgICAgICAiKSIpXQoKdDEgPC0gZGNhc3QuZGF0YS50YWJsZShtdWZiLAogICAgICAgICAgICAgICAgICAgICAgIEdlbm90eXBlICsgRGlldCB+IFdlZWssCiAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUudmFyID0gImVzdCIpCmRhdGF0YWJsZSh0MSwKICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgICBjYXB0aW9uID0gIkF2ZXJhZ2UgUmF0aW8gb2YgQmFjdGVyb2lkZXRlcyBhbmQgRmlybWljdXRlcyIsCiAgICAgICAgICBjbGFzcyA9ICJjZWxsLWJvcmRlciBzdHJpcGUiLAogICAgICAgICAgb3B0aW9ucyA9IGxpc3Qoc2VhcmNoID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlTGVuZ3RoID0gbnJvdyh0MSkpKQpgYGAKCiMgVXBkYXRlIE9UVSB0YWJsZTogZXhjdWRlZCB1bmtub3duIHBoeWx1bSBhbmQgQ3lhbm9iYWN0ZXJpYQpgYGB7ciB1cGRhdGVfb3R1fQpvdHUgPC0gZGF0YS50YWJsZShwczBAdGF4X3RhYmxlQC5EYXRhLAogICAgICAgICAgICAgICAgICB0KHBzMEBvdHVfdGFibGVALkRhdGEpKQoKIyBSZW1vdmUgU3BlY2llcyBtYXBwaW5nJwpvdHUkU3BlY2llcyA8LSBOVUxMCmRpbShvdHUpCmBgYAoKIyAxLiBQaHlsdW0KIyMgQ291bnRzIGF0IFBoeWx1bSBsZXZlbApgYGB7ciBjb3VudHNfcCwgd2FybmluZz1GQUxTRSxlY2hvPUZBTFNFLG1lc3NhZ2U9RkFMU0V9CmNvdW50c19wIDwtIGNvdW50c19ieV90YXhfcmFuayhkdDEgPSBvdHUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZ2dyX2J5ID0gIlBoeWx1bSIpCnNldG9yZGVyKGNvdW50c19wLCAtYDRBYCkKZGF0YXRhYmxlKGNvdW50c19wLAogICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSwKICAgICAgICAgIGNhcHRpb24gPSAiVGF4b25vbWljICBjb3VudCB0YWJsZSIsCiAgICAgICAgICBjbGFzcyA9ICJjZWxsLWJvcmRlciBzdHJpcGUiLAogICAgICAgICAgb3B0aW9ucyA9IGxpc3Qoc2VhcmNoID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlTGVuZ3RoID0gbnJvdyhjb3VudHNfcCkpKSAlPiUKICBmb3JtYXRDdXJyZW5jeShjb2x1bW5zID0gMjpuY29sKGNvdW50c19wKSwKICAgICAgICAgICAgICAgICBjdXJyZW5jeSA9ICIiLAogICAgICAgICAgICAgICAgIG1hcmsgPSAiLCIsCiAgICAgICAgICAgICAgICAgZGlnaXRzID0gMCkKYGBgCgojIyBSZWxhdGl2ZSBhYnVuZGFuY2UgKCUpIGF0IFBoeWx1bSBsZXZlbApgYGB7ciByYV9wLCB3YXJuaW5nPUZBTFNFLGVjaG89RkFMU0UsbWVzc2FnZT1GQUxTRX0KcmFfcCA8LSByYV9ieV90YXhfcmFuayhjb3VudHMgPSBjb3VudHNfcCwKICAgICAgICAgICAgICAgICAgICAgICBwY3QgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICBkaWdpdCA9IDQpCgpkYXRhdGFibGUocmFfcCwKICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgICBjYXB0aW9uID0gIlRheG9ub21pYyAgY291bnQgdGFibGUiLAogICAgICAgICAgY2xhc3MgPSAiY2VsbC1ib3JkZXIgc3RyaXBlIiwKICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNlYXJjaCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IG5yb3cocmFfcCkpKSAlPiUKICBmb3JtYXRQZXJjZW50YWdlKGNvbHVtbnMgPSAyOm5jb2woY291bnRzX3ApLAogICAgICAgICAgICAgICAgICAgZGlnaXRzID0gMikKYGBgCgojIyBQQ0EgYXQgUGh5bHVtIGxldmVsCmBgYHtyIHBjYV9wX3AwLCBmaWcuaGVpZ2h0ID0gNSwgZmlnLndpZHRoID0gNn0KZHRfcGNhIDwtIHQocmFfcFssIDI6bmNvbChyYV9wKV0pCmNvbG5hbWVzKGR0X3BjYSkgPC0gcmFfcCRQaHlsdW0KCmR0X3BjYV9wIDwtIGRhdGEudGFibGUoU2FtcGxlID0gcm93bmFtZXMoZHRfcGNhKSwKICAgICAgICAgICAgICAgICAgICAgICBkdF9wY2EpCmR0X3BjYV9wIDwtIG1lcmdlKHNtcGwsCiAgICAgICAgICAgICAgICAgIGR0X3BjYV9wLAogICAgICAgICAgICAgICAgICBieSA9ICJTYW1wbGUiKQoKIyBLZWVwIG9ubHkgdGhlIHBoeWx1bSB3aXRoIG5vbi16ZXJvIGNvdW50cwp0bXAgPC0gZHRfcGNhX3BbLCAxMDpuY29sKGR0X3BjYV9wKV0Ka2VlcF9wIDwtIGNvbG5hbWVzKHRtcClbY29sU3Vtcyh0bXApID4gMF0KZHRfcGNhIDwtIGR0X3BjYVssIGtlZXBfcF0KCiMgbTEgPC0gcHJjb21wKGR0X3BjYSwKIyAgICAgICAgICAgICAgY2VudGVyID0gVFJVRSwKIyAgICAgICAgICAgICAgc2NhbGUuID0gVFJVRSkKCiMgbTEgPC0gcHJjb21wKGR0X3BjYSwKIyAgICAgICAgICAgICAgY2VudGVyID0gRkFMU0UsCiMgICAgICAgICAgICAgIHNjYWxlLiA9IEZBTFNFKQoKbTEgPC0gcHJjb21wKGR0X3BjYSwKICAgICAgICAgICAgIGNlbnRlciA9IFRSVUUsCiAgICAgICAgICAgICBzY2FsZS4gPSBGQUxTRSkKCnN1bW1hcnkobTEpCgojIFNlbGVjdCBQQy1zIHRvIHBsaW90IChQQzEgJiBQQzIpCmNob2ljZXMgPC0gMToyCgojIEFkZCBtZXRhIGRhdGEKZHQuc2NyIDwtIGRhdGEudGFibGUobTEkeFssIGNob2ljZXNdKQpkdC5zY3IkU2FtcGxlIDwtIHJvd25hbWVzKG0xJHgpCgpkdC5zY3IgPC0gbWVyZ2Uoc21wbCwKICAgICAgICAgICAgICAgIGR0LnNjciwKICAgICAgICAgICAgICAgIGJ5ID0gIlNhbXBsZSIpCmR0LnNjcgoKIyBMb2FkaW5ncywgaS5lLiBhcnJvd3MgKGRmLnYpCmR0LnJvdCA8LSBhcy5kYXRhLmZyYW1lKG0xJHJvdGF0aW9uWywgY2hvaWNlc10pCmR0LnJvdCRmZWF0IDwtIHJvd25hbWVzKGR0LnJvdCkKZHQucm90IDwtIGRhdGEudGFibGUoZHQucm90KQpkdC5yb3QKCmR0LmxvYWQgPC0gbWVsdC5kYXRhLnRhYmxlKGR0LnJvdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQudmFycyA9ICJmZWF0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVhc3VyZS52YXJzID0gMToyLAogICAgICAgICAgICAgICAgICAgICAgICAgICB2YXJpYWJsZS5uYW1lID0gInBjIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUubmFtZSA9ICJsb2FkaW5nIikKZHQubG9hZCRmZWF0IDwtIGZhY3RvcihkdC5sb2FkJGZlYXQsCiAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gdW5pcXVlKGR0LmxvYWQkZmVhdCkpCiMgUGxvdCBsb2FkaW5ncwpwMCA8LSBnZ3Bsb3QoZGF0YSA9IGR0LmxvYWQsCiAgICAgICAgICAgICBhZXMoeCA9IGZlYXQsCiAgICAgICAgICAgICAgICAgeSA9IGxvYWRpbmcpKSArCiAgZmFjZXRfd3JhcCh+IHBjLAogICAgICAgICAgICAgbnJvdyA9IDIpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGdndGl0bGUoIlBDIExvYWRpbmdzIikgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAxKSkKcDAKCnRpZmYoZmlsZW5hbWUgPSAidG1wL3BjLjEuMl9sb2FkaW5nc19waHlsdW0udGlmZiIsCiAgICAgaGVpZ2h0ID0gNSwKICAgICB3aWR0aCA9IDYsCiAgICAgdW5pdHMgPSAnaW4nLAogICAgIHJlcyA9IDMwMCwKICAgICBjb21wcmVzc2lvbiA9ICJsencrcCIpCnByaW50KHAwKQpncmFwaGljcy5vZmYoKQoKcHJpbnQocDApCmBgYAoKYGBge3IgcGNhX2F4ZXNwfQojIEF4aXMgbGFiZWxzCnUuYXhpcy5sYWJzIDwtIHBhc3RlKGNvbG5hbWVzKGR0LnJvdClbMToyXSwgCiAgICAgICAgICAgICAgICAgICAgIHNwcmludGYoJyglMC4xZiUlIGV4cGxhaW5lZCB2YXIuKScsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEwMCptMSRzZGV2W2Nob2ljZXNdXjIvc3VtKG0xJHNkZXZeMikpKQp1LmF4aXMubGFicwpgYGAKCmBgYHtyIGJpcGxvdF9nZW5fcCwgZmlnLmhlaWdodCA9IDgsIGZpZy53aWR0aCA9IDh9CmNudHIgPC0gZGF0YS50YWJsZShhZ2dyZWdhdGUoeCA9IGR0LnNjciRQQzEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSBsaXN0KGR0LnNjciRHZW5vdHlwZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRlVOID0gIm1lYW4iKSwKICAgICAgICAgICAgICAgICAgIGFnZ3JlZ2F0ZSh4ID0gZHQuc2NyJFBDMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGxpc3QoZHQuc2NyJEdlbm90eXBlKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGVU4gPSAibWVhbiIpJHgpCmNvbG5hbWVzKGNudHIpIDwtIGMoIkdlbm90eXBlIiwKICAgICAgICAgICAgICAgICAgICAiUEMxIiwKICAgICAgICAgICAgICAgICAgICAiUEMyIikKCiMgQmFzZWQgb24gRmlndXJlIHAwLCBrZWVwIG9ubHkgYSBmZXcgdmFyaWFibGVzIHdpdGggaGlnaCBsb2FkaW5ncyBpbiBQQzEgYW5kIFBDMi0tLS0KZHQucm90WywgcmF0aW5nOj0gKFBDMSleMiArIChQQzIpXjJdCnNldG9yZGVyKGR0LnJvdCwgLXJhdGluZykKCiMgU2VsZWN0IHRvcCA1CmR0LnJvdCA8LSBkdC5yb3RbMTo1LCBdCgojIHZhci5rZWVwLm5keCA8LSB3aGljaChkdC5yb3QkZmVhdCAlaW4lIGMoLi4uKSkKIyBPciBzZWxlY3QgYWxsCiMgdmFyLmtlZXAubmR4IDwtIDM6bmNvbChkdDEpCiMgVXNlIGR0LnJvdFt2YXIua2VlcC5uZHgsXSBhbmQgZHQucm90JGZlYXRbdmFyLmtlZXAubmR4XQpwMSA8LSBnZ3Bsb3QoZGF0YSA9IGR0LnJvdCwKICAgICAgICAgICAgIGFlcyh4ID0gUEMxLAogICAgICAgICAgICAgICAgIHkgPSBQQzIpKSArCiAgY29vcmRfZXF1YWwoKSArCiAgZ2VvbV9wb2ludChkYXRhID0gZHQuc2NyLAogICAgICAgICAgICAgYWVzKGZpbGwgPSBHZW5vdHlwZSwKICAgICAgICAgICAgICAgICBzaGFwZSA9IGZhY3RvcihUaW1lcG9pbnQpKSwKICAgICAgICAgICAgIHNpemUgPSAzLAogICAgICAgICAgICAgYWxwaGEgPSAwLjUpICsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSAwLAogICAgICAgICAgICAgICAgICAgeSA9IDAsCiAgICAgICAgICAgICAgICAgICB4ZW5kID0gMC4yKlBDMSwKICAgICAgICAgICAgICAgICAgIHllbmQgPSAwLjIqUEMyKSwKICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdyhsZW5ndGggPSB1bml0KDEvMiwgJ3BpY2FzJykpLAogICAgICAgICAgICAgICAjIHNpemUgPSAxLCAKICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siKSArCiAgZ2VvbV90ZXh0KGFlcyh4ID0gMC4yMipQQzEsCiAgICAgICAgICAgICAgICB5ID0gMC4yMipQQzIsCiAgICAgICAgICAgICAgICBsYWJlbCA9IGR0LnJvdCRmZWF0KSwKICAgICAgICAgICAgIyBzaXplID0gNSwKICAgICAgICAgICAgaGp1c3QgPSAwLjUpICsKICBzY2FsZV94X2NvbnRpbnVvdXModS5heGlzLmxhYnNbMV0pICsKICBzY2FsZV95X2NvbnRpbnVvdXModS5heGlzLmxhYnNbMl0pICsKICBzY2FsZV9maWxsX21hbnVhbChuYW1lID0gIkdyb3VwIiwKICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBjKCJXaWxkIFR5cGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5yZjIgS08iKSwKICAgICAgICAgICAgICAgICAgICB2YWx1ZXMgPSBjKCJyZWQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImJsdWUiKSkgKwogIHNjYWxlX3NoYXBlX21hbnVhbChicmVha3MgPSAxOjMsCiAgICAgICAgICAgICAgICAgICAgIHZhbHVlcyA9IDIxOjIzKSArCiAgZ2VvbV9sYWJlbChkYXRhID0gY250ciwKICAgICAgICAgICAgIGFlcyh4ID0gUEMxLAogICAgICAgICAgICAgICAgIHkgPSBQQzIsCiAgICAgICAgICAgICAgICAgbGFiZWwgPSBHZW5vdHlwZSwKICAgICAgICAgICAgICAgICBjb2xvdXIgPSBHZW5vdHlwZSksCiAgICAgICAgICAgICBhbHBoYSA9IDAuNSwKICAgICAgICAgICAgIHNpemUgPSAzKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKGd1aWRlID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoIldpbGQgVHlwZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5yZjIgS08iKSwKICAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gYygicmVkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiYmx1ZSIpKSArCiAgZ2d0aXRsZSgiIikgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMjApLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgCgp0aWZmKGZpbGVuYW1lID0gInRtcC9waHlsdW1fYmlwbG90X2dycC50aWZmIiwKICAgICBoZWlnaHQgPSA4LAogICAgIHdpZHRoID0gOCwKICAgICB1bml0cyA9ICdpbicsCiAgICAgcmVzID0gMzAwLAogICAgIGNvbXByZXNzaW9uID0gImx6dytwIikKcHJpbnQocDEpCmdyYXBoaWNzLm9mZigpCgpnZ3Bsb3RseShwMSkKCiMgR2VuZXJpYyBiaXBsb3QKYmlwbG90KG0xKQpgYGAKCiMgMi4gQ2xhc3MKIyMgQ291bnRzIGF0IENsYXNzIGxldmVsCmBgYHtyIGNvdW50c19jLCB3YXJuaW5nPUZBTFNFLGVjaG89RkFMU0UsbWVzc2FnZT1GQUxTRX0KY291bnRzX2MgPC0gY291bnRzX2J5X3RheF9yYW5rKGR0MSA9IG90dSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFnZ3JfYnkgPSAiQ2xhc3MiKQpzZXRvcmRlcihjb3VudHNfYywgLWA0QWApCmRhdGF0YWJsZShjb3VudHNfYywKICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgICBjYXB0aW9uID0gIlRheG9ub21pYyAgY291bnQgdGFibGUiLAogICAgICAgICAgY2xhc3MgPSAiY2VsbC1ib3JkZXIgc3RyaXBlIiwKICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNlYXJjaCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IG5yb3coY291bnRzX2MpKSkgJT4lCiAgZm9ybWF0Q3VycmVuY3koY29sdW1ucyA9IDI6bmNvbChjb3VudHNfYyksCiAgICAgICAgICAgICAgICAgY3VycmVuY3kgPSAiIiwKICAgICAgICAgICAgICAgICBtYXJrID0gIiwiLAogICAgICAgICAgICAgICAgIGRpZ2l0cyA9IDApCmBgYAoKIyMgUmVsYXRpdmUgYWJ1bmRhbmNlICglKSBhdCBDbGFzcyBsZXZlbApgYGB7ciByYV9jLCB3YXJuaW5nID0gRkFMU0UsIGVjaG8gPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFfQpyYV9jIDwtIHJhX2J5X3RheF9yYW5rKGNvdW50cyA9IGNvdW50c19jLAogICAgICAgICAgICAgICAgICAgICAgIHBjdCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgIGRpZ2l0ID0gNCkKCmRhdGF0YWJsZShyYV9jLAogICAgICAgICAgcm93bmFtZXMgPSBGQUxTRSwKICAgICAgICAgIGNhcHRpb24gPSAiVGF4b25vbWljICBjb3VudCB0YWJsZSIsCiAgICAgICAgICBjbGFzcyA9ICJjZWxsLWJvcmRlciBzdHJpcGUiLAogICAgICAgICAgb3B0aW9ucyA9IGxpc3Qoc2VhcmNoID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICBwYWdlTGVuZ3RoID0gbnJvdyhyYV9jKSkpICU+JQogIGZvcm1hdFBlcmNlbnRhZ2UoY29sdW1ucyA9IDI6bmNvbChjb3VudHNfYyksCiAgICAgICAgICAgICAgICAgICBkaWdpdHMgPSAyKQpgYGAKCiMjIFBDQSBhdCBDbGFzcyBsZXZlbApgYGB7ciBwY2FfY19wMCwgZmlnLmhlaWdodCA9IDUsIGZpZy53aWR0aCA9IDZ9CmR0X3BjYSA8LSB0KHJhX2NbLCAyOm5jb2wocmFfYyldKQpjb2xuYW1lcyhkdF9wY2EpIDwtIHJhX2MkQ2xhc3MKCmR0X3BjYV9jIDwtIGRhdGEudGFibGUoU2FtcGxlID0gcm93bmFtZXMoZHRfcGNhKSwKICAgICAgICAgICAgICAgICAgICAgICBkdF9wY2EpCmR0X3BjYV9jIDwtIG1lcmdlKHNtcGwsCiAgICAgICAgICAgICAgICAgIGR0X3BjYV9jLAogICAgICAgICAgICAgICAgICBieSA9ICJTYW1wbGUiKQoKIyBLZWVwIG9ubHkgdGhlIENsYXNzIHdpdGggbm9uLXplcm8gY291bnRzCnRtcCA8LSBkdF9wY2FfY1ssIDEwOm5jb2woZHRfcGNhX2MpXQprZWVwX2MgPC0gY29sbmFtZXModG1wKVtjb2xTdW1zKHRtcCkgPiAwXQpkdF9wY2EgPC0gZHRfcGNhWywga2VlcF9jXQoKbTEgPC0gcHJjb21wKGR0X3BjYSwKICAgICAgICAgICAgIGNlbnRlciA9IFRSVUUsCiAgICAgICAgICAgICBzY2FsZS4gPSBGQUxTRSkKCnN1bW1hcnkobTEpCgojIFNlbGVjdCBQQy1zIHRvIHBsaW90IChQQzEgJiBQQzIpCmNob2ljZXMgPC0gMToyCgojIEFkZCBtZXRhIGRhdGEKZHQuc2NyIDwtIGRhdGEudGFibGUobTEkeFssIGNob2ljZXNdKQpkdC5zY3IkU2FtcGxlIDwtIHJvd25hbWVzKG0xJHgpCgpkdC5zY3IgPC0gbWVyZ2Uoc21wbCwKICAgICAgICAgICAgICAgIGR0LnNjciwKICAgICAgICAgICAgICAgIGJ5ID0gIlNhbXBsZSIpCmR0LnNjcgoKIyBMb2FkaW5ncywgaS5lLiBhcnJvd3MgKGRmLnYpCmR0LnJvdCA8LSBhcy5kYXRhLmZyYW1lKG0xJHJvdGF0aW9uWywgY2hvaWNlc10pCmR0LnJvdCRmZWF0IDwtIHJvd25hbWVzKGR0LnJvdCkKZHQucm90IDwtIGRhdGEudGFibGUoZHQucm90KQpkdC5yb3QKCmR0LmxvYWQgPC0gbWVsdC5kYXRhLnRhYmxlKGR0LnJvdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQudmFycyA9ICJmZWF0IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVhc3VyZS52YXJzID0gMToyLAogICAgICAgICAgICAgICAgICAgICAgICAgICB2YXJpYWJsZS5uYW1lID0gInBjIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUubmFtZSA9ICJsb2FkaW5nIikKZHQubG9hZCRmZWF0IDwtIGZhY3RvcihkdC5sb2FkJGZlYXQsCiAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gdW5pcXVlKGR0LmxvYWQkZmVhdCkpCiMgUGxvdCBsb2FkaW5ncwpwMCA8LSBnZ3Bsb3QoZGF0YSA9IGR0LmxvYWQsCiAgICAgICAgICAgICBhZXMoeCA9IGZlYXQsCiAgICAgICAgICAgICAgICAgeSA9IGxvYWRpbmcpKSArCiAgZmFjZXRfd3JhcCh+IHBjLAogICAgICAgICAgICAgbnJvdyA9IDIpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGdndGl0bGUoIlBDIExvYWRpbmdzIikgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGp1c3QgPSAxKSkKcDAKCnRpZmYoZmlsZW5hbWUgPSAidG1wL3BjLjEuMl9sb2FkaW5nc19DbGFzcy50aWZmIiwKICAgICBoZWlnaHQgPSA1LAogICAgIHdpZHRoID0gNiwKICAgICB1bml0cyA9ICdpbicsCiAgICAgcmVzID0gMzAwLAogICAgIGNvbXByZXNzaW9uID0gImx6dytwIikKcHJpbnQocDApCmdyYXBoaWNzLm9mZigpCgpwcmludChwMCkKYGBgCgpgYGB7ciBwY2FfYXhlc19jfQojIEF4aXMgbGFiZWxzCnUuYXhpcy5sYWJzIDwtIHBhc3RlKGNvbG5hbWVzKGR0LnJvdClbMToyXSwgCiAgICAgICAgICAgICAgICAgICAgIHNwcmludGYoJyglMC4xZiUlIGV4cGxhaW5lZCB2YXIuKScsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIDEwMCptMSRzZGV2W2Nob2ljZXNdXjIvc3VtKG0xJHNkZXZeMikpKQp1LmF4aXMubGFicwpgYGAKCmBgYHtyIGJpcGxvdF9nZW5fYywgZmlnLmhlaWdodCA9IDgsIGZpZy53aWR0aCA9IDh9CmNudHIgPC0gZGF0YS50YWJsZShhZ2dyZWdhdGUoeCA9IGR0LnNjciRQQzEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSBsaXN0KGR0LnNjciRHZW5vdHlwZSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRlVOID0gIm1lYW4iKSwKICAgICAgICAgICAgICAgICAgIGFnZ3JlZ2F0ZSh4ID0gZHQuc2NyJFBDMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGxpc3QoZHQuc2NyJEdlbm90eXBlKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGVU4gPSAibWVhbiIpJHgpCmNvbG5hbWVzKGNudHIpIDwtIGMoIkdlbm90eXBlIiwKICAgICAgICAgICAgICAgICAgICAiUEMxIiwKICAgICAgICAgICAgICAgICAgICAiUEMyIikKCiMgQmFzZWQgb24gRmlndXJlIHAwLCBrZWVwIG9ubHkgYSBmZXcgdmFyaWFibGVzIHdpdGggaGlnaCBsb2FkaW5ncyBpbiBQQzEgYW5kIFBDMi0tLS0KZHQucm90WywgcmF0aW5nOj0gKFBDMSleMiArIChQQzIpXjJdCnNldG9yZGVyKGR0LnJvdCwgLXJhdGluZykKCiMgU2VsZWN0IHRvcCA4CmR0LnJvdCA8LSBkdC5yb3RbMTo4LCBdCgojIHZhci5rZWVwLm5keCA8LSB3aGljaChkdC5yb3QkZmVhdCAlaW4lIGMoLi4uKSkKIyBPciBzZWxlY3QgYWxsCiMgdmFyLmtlZXAubmR4IDwtIDM6bmNvbChkdDEpCiMgVXNlIGR0LnJvdFt2YXIua2VlcC5uZHgsXSBhbmQgZHQucm90JGZlYXRbdmFyLmtlZXAubmR4XQpwMSA8LSBnZ3Bsb3QoZGF0YSA9IGR0LnJvdCwKICAgICAgICAgICAgIGFlcyh4ID0gUEMxLAogICAgICAgICAgICAgICAgIHkgPSBQQzIpKSArCiAgY29vcmRfZXF1YWwoKSArCiAgZ2VvbV9wb2ludChkYXRhID0gZHQuc2NyLAogICAgICAgICAgICAgYWVzKGZpbGwgPSBHZW5vdHlwZSwKICAgICAgICAgICAgICAgICBzaGFwZSA9IGZhY3RvcihUaW1lcG9pbnQpKSwKICAgICAgICAgICAgIHNpemUgPSAzLAogICAgICAgICAgICAgYWxwaGEgPSAwLjUpICsKICBnZW9tX3NlZ21lbnQoYWVzKHggPSAwLAogICAgICAgICAgICAgICAgICAgeSA9IDAsCiAgICAgICAgICAgICAgICAgICB4ZW5kID0gMC4yKlBDMSwKICAgICAgICAgICAgICAgICAgIHllbmQgPSAwLjIqUEMyKSwKICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdyhsZW5ndGggPSB1bml0KDEvMiwgJ3BpY2FzJykpLAogICAgICAgICAgICAgICAjIHNpemUgPSAxLCAKICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siKSArCiAgZ2VvbV90ZXh0KGFlcyh4ID0gMC4yMipQQzEsCiAgICAgICAgICAgICAgICB5ID0gMC4yMipQQzIsCiAgICAgICAgICAgICAgICBsYWJlbCA9IGR0LnJvdCRmZWF0KSwKICAgICAgICAgICAgIyBzaXplID0gNSwKICAgICAgICAgICAgaGp1c3QgPSAwLjUpICsKICBzY2FsZV94X2NvbnRpbnVvdXModS5heGlzLmxhYnNbMV0pICsKICBzY2FsZV95X2NvbnRpbnVvdXModS5heGlzLmxhYnNbMl0pICsKICBzY2FsZV9maWxsX21hbnVhbChuYW1lID0gIkdyb3VwIiwKICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBjKCJXaWxkIFR5cGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5yZjIgS08iKSwKICAgICAgICAgICAgICAgICAgICB2YWx1ZXMgPSBjKCJyZWQiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImJsdWUiKSkgKwogIHNjYWxlX3NoYXBlX21hbnVhbChicmVha3MgPSAxOjMsCiAgICAgICAgICAgICAgICAgICAgIHZhbHVlcyA9IDIxOjIzKSArCiAgZ2VvbV9sYWJlbChkYXRhID0gY250ciwKICAgICAgICAgICAgIGFlcyh4ID0gUEMxLAogICAgICAgICAgICAgICAgIHkgPSBQQzIsCiAgICAgICAgICAgICAgICAgbGFiZWwgPSBHZW5vdHlwZSwKICAgICAgICAgICAgICAgICBjb2xvdXIgPSBHZW5vdHlwZSksCiAgICAgICAgICAgICBhbHBoYSA9IDAuNSwKICAgICAgICAgICAgIHNpemUgPSAzKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKGd1aWRlID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoIldpbGQgVHlwZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5yZjIgS08iKSwKICAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gYygicmVkIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiYmx1ZSIpKSArCiAgZ2d0aXRsZSgiIikgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMjApLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgCgp0aWZmKGZpbGVuYW1lID0gInRtcC9jbGFzc19iaXBsb3RfZ2VuLnRpZmYiLAogICAgIGhlaWdodCA9IDgsCiAgICAgd2lkdGggPSA4LAogICAgIHVuaXRzID0gJ2luJywKICAgICByZXMgPSAzMDAsCiAgICAgY29tcHJlc3Npb24gPSAibHp3K3AiKQpwcmludChwMSkKZ3JhcGhpY3Mub2ZmKCkKCmdncGxvdGx5KHAxKQoKIyBHZW5lcmljIGJpcGxvdApiaXBsb3QobTEpCmBgYAoKIyMgMy4gT3JkZXIKCiMjIDQuIEZhbWlseQoKIyMgNSBHZXVzCiMjIENvdW50cyBhdCBHZW51cyBsZXZlbApgYGB7ciBjb3VudHNfZywgd2FybmluZyA9IEZBTFNFLCBlY2hvID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRX0KY291bnRzX2cgPC0gY291bnRzX2J5X3RheF9yYW5rKGR0MSA9IG90dSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFnZ3JfYnkgPSAiR2VudXMiKQp0bXAgPC0gdW5pcXVlKG90dVssIEtpbmdkb206R2VudXNdKQpjb3VudHNfZ19hbGwgPC0gbWVyZ2UodG1wLAogICAgICAgICAgICAgICAgICAgICAgY291bnRzX2csCiAgICAgICAgICAgICAgICAgICAgICBieSA9ICJHZW51cyIpCgpzZXRvcmRlcihjb3VudHNfZ19hbGwsIC1gNEFgKQpkYXRhdGFibGUoY291bnRzX2csCiAgICAgICAgICByb3duYW1lcyA9IEZBTFNFLAogICAgICAgICAgY2FwdGlvbiA9ICJUYXhvbm9taWMgIGNvdW50IHRhYmxlIiwKICAgICAgICAgIGNsYXNzID0gImNlbGwtYm9yZGVyIHN0cmlwZSIsCiAgICAgICAgICBvcHRpb25zID0gbGlzdChzZWFyY2ggPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIHBhZ2VMZW5ndGggPSBucm93KGNvdW50c19nKSkpICU+JQogIGZvcm1hdEN1cnJlbmN5KGNvbHVtbnMgPSA3Om5jb2woY291bnRzX2cpLAogICAgICAgICAgICAgICAgIGN1cnJlbmN5ID0gIiIsCiAgICAgICAgICAgICAgICAgbWFyayA9ICIsIiwKICAgICAgICAgICAgICAgICBkaWdpdHMgPSAwKQpgYGAKCiMjIFJlbGF0aXZlIGFidW5kYW5jZSAoJSkgYXQgR2VudXMgbGV2ZWwKYGBge3IgcmFfZywgd2FybmluZyA9IEZBTFNFLCBlY2hvID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRX0KcmFfZyA8LSByYV9ieV90YXhfcmFuayhjb3VudHMgPSBjb3VudHNfZywKICAgICAgICAgICAgICAgICAgICAgICBwY3QgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICBkaWdpdCA9IDQpCgpkYXRhdGFibGUocmFfZywKICAgICAgICAgIHJvd25hbWVzID0gRkFMU0UsCiAgICAgICAgICBjYXB0aW9uID0gIlRheG9ub21pYyAgY291bnQgdGFibGUiLAogICAgICAgICAgY2xhc3MgPSAiY2VsbC1ib3JkZXIgc3RyaXBlIiwKICAgICAgICAgIG9wdGlvbnMgPSBsaXN0KHNlYXJjaCA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgcGFnZUxlbmd0aCA9IG5yb3cocmFfZykpKSAlPiUKICBmb3JtYXRQZXJjZW50YWdlKGNvbHVtbnMgPSAyOm5jb2woY291bnRzX2cpLAogICAgICAgICAgICAgICAgICAgZGlnaXRzID0gMikKYGBgCgojIFNlc3Npb24gSW5mb3JtYXRpb24KYGBge3IgaW5mbyxldmFsPVRSVUV9CnNlc3Npb25JbmZvKCkKYGBg